diff options
| -rw-r--r-- | fs/cifs/cifs_debug.c | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 14 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 41 | ||||
| -rw-r--r-- | fs/cifs/smb2ops.c | 134 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 21 | ||||
| -rw-r--r-- | fs/cifs/smbdirect.c | 8 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 2 |
8 files changed, 173 insertions, 51 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 6a69f11aacf7..45e74da40f3a 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -380,6 +380,8 @@ skip_rdma: | |||
| 380 | atomic_read(&server->in_send), | 380 | atomic_read(&server->in_send), |
| 381 | atomic_read(&server->num_waiters)); | 381 | atomic_read(&server->num_waiters)); |
| 382 | #endif | 382 | #endif |
| 383 | /* dump session id helpful for use with network trace */ | ||
| 384 | seq_printf(m, " SessionId: 0x%llx", ses->Suid); | ||
| 383 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | 385 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) |
| 384 | seq_puts(m, " encrypted"); | 386 | seq_puts(m, " encrypted"); |
| 385 | if (ses->sign) | 387 | if (ses->sign) |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b1a5fcfa3ce1..f5fcd6360056 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -878,6 +878,9 @@ out: | |||
| 878 | 878 | ||
| 879 | static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) | 879 | static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) |
| 880 | { | 880 | { |
| 881 | struct cifsFileInfo *cfile = file->private_data; | ||
| 882 | struct cifs_tcon *tcon; | ||
| 883 | |||
| 881 | /* | 884 | /* |
| 882 | * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate | 885 | * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate |
| 883 | * the cached file length | 886 | * the cached file length |
| @@ -909,6 +912,12 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) | |||
| 909 | if (rc < 0) | 912 | if (rc < 0) |
| 910 | return (loff_t)rc; | 913 | return (loff_t)rc; |
| 911 | } | 914 | } |
| 915 | if (cfile && cfile->tlink) { | ||
| 916 | tcon = tlink_tcon(cfile->tlink); | ||
| 917 | if (tcon->ses->server->ops->llseek) | ||
| 918 | return tcon->ses->server->ops->llseek(file, tcon, | ||
| 919 | offset, whence); | ||
| 920 | } | ||
| 912 | return generic_file_llseek(file, offset, whence); | 921 | return generic_file_llseek(file, offset, whence); |
| 913 | } | 922 | } |
| 914 | 923 | ||
| @@ -1070,11 +1079,6 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, | |||
| 1070 | 1079 | ||
| 1071 | cifs_dbg(FYI, "copychunk range\n"); | 1080 | cifs_dbg(FYI, "copychunk range\n"); |
| 1072 | 1081 | ||
| 1073 | if (src_inode == target_inode) { | ||
| 1074 | rc = -EINVAL; | ||
| 1075 | goto out; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | if (!src_file->private_data || !dst_file->private_data) { | 1082 | if (!src_file->private_data || !dst_file->private_data) { |
| 1079 | rc = -EBADF; | 1083 | rc = -EBADF; |
| 1080 | cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); | 1084 | cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 33c251b408aa..334ff5f9c3f3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -497,6 +497,8 @@ struct smb_version_operations { | |||
| 497 | /* version specific fiemap implementation */ | 497 | /* version specific fiemap implementation */ |
| 498 | int (*fiemap)(struct cifs_tcon *tcon, struct cifsFileInfo *, | 498 | int (*fiemap)(struct cifs_tcon *tcon, struct cifsFileInfo *, |
| 499 | struct fiemap_extent_info *, u64, u64); | 499 | struct fiemap_extent_info *, u64, u64); |
| 500 | /* version specific llseek implementation */ | ||
| 501 | loff_t (*llseek)(struct file *, struct cifs_tcon *, loff_t, int); | ||
| 500 | }; | 502 | }; |
| 501 | 503 | ||
| 502 | struct smb_version_values { | 504 | struct smb_version_values { |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 084756cfdaee..8c4121da624e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -528,6 +528,21 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 528 | /* do not want to be sending data on a socket we are freeing */ | 528 | /* do not want to be sending data on a socket we are freeing */ |
| 529 | cifs_dbg(FYI, "%s: tearing down socket\n", __func__); | 529 | cifs_dbg(FYI, "%s: tearing down socket\n", __func__); |
| 530 | mutex_lock(&server->srv_mutex); | 530 | mutex_lock(&server->srv_mutex); |
| 531 | if (server->ssocket) { | ||
| 532 | cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", | ||
| 533 | server->ssocket->state, server->ssocket->flags); | ||
| 534 | kernel_sock_shutdown(server->ssocket, SHUT_WR); | ||
| 535 | cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", | ||
| 536 | server->ssocket->state, server->ssocket->flags); | ||
| 537 | sock_release(server->ssocket); | ||
| 538 | server->ssocket = NULL; | ||
| 539 | } | ||
| 540 | server->sequence_number = 0; | ||
| 541 | server->session_estab = false; | ||
| 542 | kfree(server->session_key.response); | ||
| 543 | server->session_key.response = NULL; | ||
| 544 | server->session_key.len = 0; | ||
| 545 | server->lstrp = jiffies; | ||
| 531 | 546 | ||
| 532 | /* mark submitted MIDs for retry and issue callback */ | 547 | /* mark submitted MIDs for retry and issue callback */ |
| 533 | INIT_LIST_HEAD(&retry_list); | 548 | INIT_LIST_HEAD(&retry_list); |
| @@ -540,6 +555,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 540 | list_move(&mid_entry->qhead, &retry_list); | 555 | list_move(&mid_entry->qhead, &retry_list); |
| 541 | } | 556 | } |
| 542 | spin_unlock(&GlobalMid_Lock); | 557 | spin_unlock(&GlobalMid_Lock); |
| 558 | mutex_unlock(&server->srv_mutex); | ||
| 543 | 559 | ||
| 544 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); | 560 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); |
| 545 | list_for_each_safe(tmp, tmp2, &retry_list) { | 561 | list_for_each_safe(tmp, tmp2, &retry_list) { |
| @@ -548,24 +564,11 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 548 | mid_entry->callback(mid_entry); | 564 | mid_entry->callback(mid_entry); |
| 549 | } | 565 | } |
| 550 | 566 | ||
| 551 | if (server->ssocket) { | 567 | if (cifs_rdma_enabled(server)) { |
| 552 | cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", | 568 | mutex_lock(&server->srv_mutex); |
| 553 | server->ssocket->state, server->ssocket->flags); | ||
| 554 | kernel_sock_shutdown(server->ssocket, SHUT_WR); | ||
| 555 | cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", | ||
| 556 | server->ssocket->state, server->ssocket->flags); | ||
| 557 | sock_release(server->ssocket); | ||
| 558 | server->ssocket = NULL; | ||
| 559 | } else if (cifs_rdma_enabled(server)) | ||
| 560 | smbd_destroy(server); | 569 | smbd_destroy(server); |
| 561 | server->sequence_number = 0; | 570 | mutex_unlock(&server->srv_mutex); |
| 562 | server->session_estab = false; | 571 | } |
| 563 | kfree(server->session_key.response); | ||
| 564 | server->session_key.response = NULL; | ||
| 565 | server->session_key.len = 0; | ||
| 566 | server->lstrp = jiffies; | ||
| 567 | |||
| 568 | mutex_unlock(&server->srv_mutex); | ||
| 569 | 572 | ||
| 570 | do { | 573 | do { |
| 571 | try_to_freeze(); | 574 | try_to_freeze(); |
| @@ -2443,6 +2446,10 @@ match_port(struct TCP_Server_Info *server, struct sockaddr *addr) | |||
| 2443 | { | 2446 | { |
| 2444 | __be16 port, *sport; | 2447 | __be16 port, *sport; |
| 2445 | 2448 | ||
| 2449 | /* SMBDirect manages its own ports, don't match it here */ | ||
| 2450 | if (server->rdma) | ||
| 2451 | return true; | ||
| 2452 | |||
| 2446 | switch (addr->sa_family) { | 2453 | switch (addr->sa_family) { |
| 2447 | case AF_INET: | 2454 | case AF_INET: |
| 2448 | sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; | 2455 | sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index a930c8965e5c..e921e6511728 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * SMB2 version specific operations | 3 | * SMB2 version specific operations |
| 3 | * | 4 | * |
| @@ -282,7 +283,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
| 282 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); | 283 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); |
| 283 | 284 | ||
| 284 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 285 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
| 285 | cifs_dbg(VFS, "encrypted frame parsing not supported yet"); | 286 | cifs_dbg(VFS, "Encrypted frame parsing not supported yet\n"); |
| 286 | return NULL; | 287 | return NULL; |
| 287 | } | 288 | } |
| 288 | 289 | ||
| @@ -324,6 +325,7 @@ static int | |||
| 324 | smb2_negotiate(const unsigned int xid, struct cifs_ses *ses) | 325 | smb2_negotiate(const unsigned int xid, struct cifs_ses *ses) |
| 325 | { | 326 | { |
| 326 | int rc; | 327 | int rc; |
| 328 | |||
| 327 | ses->server->CurrentMid = 0; | 329 | ses->server->CurrentMid = 0; |
| 328 | rc = SMB2_negotiate(xid, ses); | 330 | rc = SMB2_negotiate(xid, ses); |
| 329 | /* BB we probably don't need to retry with modern servers */ | 331 | /* BB we probably don't need to retry with modern servers */ |
| @@ -789,8 +791,6 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 789 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 791 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
| 790 | else | 792 | else |
| 791 | close_shroot(&tcon->crfid); | 793 | close_shroot(&tcon->crfid); |
| 792 | |||
| 793 | return; | ||
| 794 | } | 794 | } |
| 795 | 795 | ||
| 796 | static void | 796 | static void |
| @@ -818,7 +818,6 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 818 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, | 818 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, |
| 819 | FS_DEVICE_INFORMATION); | 819 | FS_DEVICE_INFORMATION); |
| 820 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 820 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
| 821 | return; | ||
| 822 | } | 821 | } |
| 823 | 822 | ||
| 824 | static int | 823 | static int |
| @@ -906,9 +905,8 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, | |||
| 906 | value = &src->ea_data[src->ea_name_length + 1]; | 905 | value = &src->ea_data[src->ea_name_length + 1]; |
| 907 | value_len = (size_t)le16_to_cpu(src->ea_value_length); | 906 | value_len = (size_t)le16_to_cpu(src->ea_value_length); |
| 908 | 907 | ||
| 909 | if (name_len == 0) { | 908 | if (name_len == 0) |
| 910 | break; | 909 | break; |
| 911 | } | ||
| 912 | 910 | ||
| 913 | if (src_size < 8 + name_len + 1 + value_len) { | 911 | if (src_size < 8 + name_len + 1 + value_len) { |
| 914 | cifs_dbg(FYI, "EA entry goes beyond length of list\n"); | 912 | cifs_dbg(FYI, "EA entry goes beyond length of list\n"); |
| @@ -1161,6 +1159,7 @@ static void | |||
| 1161 | smb2_clear_stats(struct cifs_tcon *tcon) | 1159 | smb2_clear_stats(struct cifs_tcon *tcon) |
| 1162 | { | 1160 | { |
| 1163 | int i; | 1161 | int i; |
| 1162 | |||
| 1164 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { | 1163 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { |
| 1165 | atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0); | 1164 | atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0); |
| 1166 | atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0); | 1165 | atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0); |
| @@ -1529,7 +1528,7 @@ smb2_copychunk_range(const unsigned int xid, | |||
| 1529 | if (pcchunk == NULL) | 1528 | if (pcchunk == NULL) |
| 1530 | return -ENOMEM; | 1529 | return -ENOMEM; |
| 1531 | 1530 | ||
| 1532 | cifs_dbg(FYI, "in smb2_copychunk_range - about to call request res key\n"); | 1531 | cifs_dbg(FYI, "%s: about to call request res key\n", __func__); |
| 1533 | /* Request a key from the server to identify the source of the copy */ | 1532 | /* Request a key from the server to identify the source of the copy */ |
| 1534 | rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink), | 1533 | rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink), |
| 1535 | srcfile->fid.persistent_fid, | 1534 | srcfile->fid.persistent_fid, |
| @@ -1649,6 +1648,7 @@ static unsigned int | |||
| 1649 | smb2_read_data_offset(char *buf) | 1648 | smb2_read_data_offset(char *buf) |
| 1650 | { | 1649 | { |
| 1651 | struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; | 1650 | struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; |
| 1651 | |||
| 1652 | return rsp->DataOffset; | 1652 | return rsp->DataOffset; |
| 1653 | } | 1653 | } |
| 1654 | 1654 | ||
| @@ -1777,7 +1777,7 @@ smb2_duplicate_extents(const unsigned int xid, | |||
| 1777 | dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off); | 1777 | dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off); |
| 1778 | dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off); | 1778 | dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off); |
| 1779 | dup_ext_buf.ByteCount = cpu_to_le64(len); | 1779 | dup_ext_buf.ByteCount = cpu_to_le64(len); |
| 1780 | cifs_dbg(FYI, "duplicate extents: src off %lld dst off %lld len %lld", | 1780 | cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n", |
| 1781 | src_off, dest_off, len); | 1781 | src_off, dest_off, len); |
| 1782 | 1782 | ||
| 1783 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); | 1783 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); |
| @@ -1794,7 +1794,7 @@ smb2_duplicate_extents(const unsigned int xid, | |||
| 1794 | &ret_data_len); | 1794 | &ret_data_len); |
| 1795 | 1795 | ||
| 1796 | if (ret_data_len > 0) | 1796 | if (ret_data_len > 0) |
| 1797 | cifs_dbg(FYI, "non-zero response length in duplicate extents"); | 1797 | cifs_dbg(FYI, "Non-zero response length in duplicate extents\n"); |
| 1798 | 1798 | ||
| 1799 | duplicate_extents_out: | 1799 | duplicate_extents_out: |
| 1800 | return rc; | 1800 | return rc; |
| @@ -1983,9 +1983,9 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 1983 | } | 1983 | } |
| 1984 | 1984 | ||
| 1985 | /* | 1985 | /* |
| 1986 | * If we negotiate SMB2 protocol and get STATUS_PENDING - update | 1986 | * If we negotiate SMB2 protocol and get STATUS_PENDING - update |
| 1987 | * the number of credits and return true. Otherwise - return false. | 1987 | * the number of credits and return true. Otherwise - return false. |
| 1988 | */ | 1988 | */ |
| 1989 | static bool | 1989 | static bool |
| 1990 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server) | 1990 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server) |
| 1991 | { | 1991 | { |
| @@ -2306,7 +2306,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
| 2306 | struct get_dfs_referral_rsp *dfs_rsp = NULL; | 2306 | struct get_dfs_referral_rsp *dfs_rsp = NULL; |
| 2307 | u32 dfs_req_size = 0, dfs_rsp_size = 0; | 2307 | u32 dfs_req_size = 0, dfs_rsp_size = 0; |
| 2308 | 2308 | ||
| 2309 | cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name); | 2309 | cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name); |
| 2310 | 2310 | ||
| 2311 | /* | 2311 | /* |
| 2312 | * Try to use the IPC tcon, otherwise just use any | 2312 | * Try to use the IPC tcon, otherwise just use any |
| @@ -2360,7 +2360,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
| 2360 | 2360 | ||
| 2361 | if (rc) { | 2361 | if (rc) { |
| 2362 | if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) | 2362 | if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) |
| 2363 | cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc); | 2363 | cifs_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); |
| 2364 | goto out; | 2364 | goto out; |
| 2365 | } | 2365 | } |
| 2366 | 2366 | ||
| @@ -2369,7 +2369,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
| 2369 | nls_codepage, remap, search_name, | 2369 | nls_codepage, remap, search_name, |
| 2370 | true /* is_unicode */); | 2370 | true /* is_unicode */); |
| 2371 | if (rc) { | 2371 | if (rc) { |
| 2372 | cifs_dbg(VFS, "parse error in smb2_get_dfs_refer rc=%d\n", rc); | 2372 | cifs_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc); |
| 2373 | goto out; | 2373 | goto out; |
| 2374 | } | 2374 | } |
| 2375 | 2375 | ||
| @@ -2745,7 +2745,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | |||
| 2745 | inode = d_inode(cfile->dentry); | 2745 | inode = d_inode(cfile->dentry); |
| 2746 | cifsi = CIFS_I(inode); | 2746 | cifsi = CIFS_I(inode); |
| 2747 | 2747 | ||
| 2748 | trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, | 2748 | trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, |
| 2749 | ses->Suid, offset, len); | 2749 | ses->Suid, offset, len); |
| 2750 | 2750 | ||
| 2751 | 2751 | ||
| @@ -2759,7 +2759,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | |||
| 2759 | return rc; | 2759 | return rc; |
| 2760 | } | 2760 | } |
| 2761 | 2761 | ||
| 2762 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | 2762 | cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); |
| 2763 | 2763 | ||
| 2764 | fsctl_buf.FileOffset = cpu_to_le64(offset); | 2764 | fsctl_buf.FileOffset = cpu_to_le64(offset); |
| 2765 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | 2765 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); |
| @@ -2816,7 +2816,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | |||
| 2816 | return rc; | 2816 | return rc; |
| 2817 | } | 2817 | } |
| 2818 | 2818 | ||
| 2819 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | 2819 | cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); |
| 2820 | 2820 | ||
| 2821 | fsctl_buf.FileOffset = cpu_to_le64(offset); | 2821 | fsctl_buf.FileOffset = cpu_to_le64(offset); |
| 2822 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | 2822 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); |
| @@ -2922,6 +2922,90 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, | |||
| 2922 | return rc; | 2922 | return rc; |
| 2923 | } | 2923 | } |
| 2924 | 2924 | ||
| 2925 | static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence) | ||
| 2926 | { | ||
| 2927 | struct cifsFileInfo *wrcfile, *cfile = file->private_data; | ||
| 2928 | struct cifsInodeInfo *cifsi; | ||
| 2929 | struct inode *inode; | ||
| 2930 | int rc = 0; | ||
| 2931 | struct file_allocated_range_buffer in_data, *out_data = NULL; | ||
| 2932 | u32 out_data_len; | ||
| 2933 | unsigned int xid; | ||
| 2934 | |||
| 2935 | if (whence != SEEK_HOLE && whence != SEEK_DATA) | ||
| 2936 | return generic_file_llseek(file, offset, whence); | ||
| 2937 | |||
| 2938 | inode = d_inode(cfile->dentry); | ||
| 2939 | cifsi = CIFS_I(inode); | ||
| 2940 | |||
| 2941 | if (offset < 0 || offset >= i_size_read(inode)) | ||
| 2942 | return -ENXIO; | ||
| 2943 | |||
| 2944 | xid = get_xid(); | ||
| 2945 | /* | ||
| 2946 | * We need to be sure that all dirty pages are written as they | ||
| 2947 | * might fill holes on the server. | ||
| 2948 | * Note that we also MUST flush any written pages since at least | ||
| 2949 | * some servers (Windows2016) will not reflect recent writes in | ||
| 2950 | * QUERY_ALLOCATED_RANGES until SMB2_flush is called. | ||
| 2951 | */ | ||
| 2952 | wrcfile = find_writable_file(cifsi, false); | ||
| 2953 | if (wrcfile) { | ||
| 2954 | filemap_write_and_wait(inode->i_mapping); | ||
| 2955 | smb2_flush_file(xid, tcon, &wrcfile->fid); | ||
| 2956 | cifsFileInfo_put(wrcfile); | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) { | ||
| 2960 | if (whence == SEEK_HOLE) | ||
| 2961 | offset = i_size_read(inode); | ||
| 2962 | goto lseek_exit; | ||
| 2963 | } | ||
| 2964 | |||
| 2965 | in_data.file_offset = cpu_to_le64(offset); | ||
| 2966 | in_data.length = cpu_to_le64(i_size_read(inode)); | ||
| 2967 | |||
| 2968 | rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, | ||
| 2969 | cfile->fid.volatile_fid, | ||
| 2970 | FSCTL_QUERY_ALLOCATED_RANGES, true, | ||
| 2971 | (char *)&in_data, sizeof(in_data), | ||
| 2972 | sizeof(struct file_allocated_range_buffer), | ||
| 2973 | (char **)&out_data, &out_data_len); | ||
| 2974 | if (rc == -E2BIG) | ||
| 2975 | rc = 0; | ||
| 2976 | if (rc) | ||
| 2977 | goto lseek_exit; | ||
| 2978 | |||
| 2979 | if (whence == SEEK_HOLE && out_data_len == 0) | ||
| 2980 | goto lseek_exit; | ||
| 2981 | |||
| 2982 | if (whence == SEEK_DATA && out_data_len == 0) { | ||
| 2983 | rc = -ENXIO; | ||
| 2984 | goto lseek_exit; | ||
| 2985 | } | ||
| 2986 | |||
| 2987 | if (out_data_len < sizeof(struct file_allocated_range_buffer)) { | ||
| 2988 | rc = -EINVAL; | ||
| 2989 | goto lseek_exit; | ||
| 2990 | } | ||
| 2991 | if (whence == SEEK_DATA) { | ||
| 2992 | offset = le64_to_cpu(out_data->file_offset); | ||
| 2993 | goto lseek_exit; | ||
| 2994 | } | ||
| 2995 | if (offset < le64_to_cpu(out_data->file_offset)) | ||
| 2996 | goto lseek_exit; | ||
| 2997 | |||
| 2998 | offset = le64_to_cpu(out_data->file_offset) + le64_to_cpu(out_data->length); | ||
| 2999 | |||
| 3000 | lseek_exit: | ||
| 3001 | free_xid(xid); | ||
| 3002 | kfree(out_data); | ||
| 3003 | if (!rc) | ||
| 3004 | return vfs_setpos(file, offset, inode->i_sb->s_maxbytes); | ||
| 3005 | else | ||
| 3006 | return rc; | ||
| 3007 | } | ||
| 3008 | |||
| 2925 | static int smb3_fiemap(struct cifs_tcon *tcon, | 3009 | static int smb3_fiemap(struct cifs_tcon *tcon, |
| 2926 | struct cifsFileInfo *cfile, | 3010 | struct cifsFileInfo *cfile, |
| 2927 | struct fiemap_extent_info *fei, u64 start, u64 len) | 3011 | struct fiemap_extent_info *fei, u64 start, u64 len) |
| @@ -3384,7 +3468,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
| 3384 | 3468 | ||
| 3385 | req = aead_request_alloc(tfm, GFP_KERNEL); | 3469 | req = aead_request_alloc(tfm, GFP_KERNEL); |
| 3386 | if (!req) { | 3470 | if (!req) { |
| 3387 | cifs_dbg(VFS, "%s: Failed to alloc aead request", __func__); | 3471 | cifs_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); |
| 3388 | return -ENOMEM; | 3472 | return -ENOMEM; |
| 3389 | } | 3473 | } |
| 3390 | 3474 | ||
| @@ -3395,7 +3479,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
| 3395 | 3479 | ||
| 3396 | sg = init_sg(num_rqst, rqst, sign); | 3480 | sg = init_sg(num_rqst, rqst, sign); |
| 3397 | if (!sg) { | 3481 | if (!sg) { |
| 3398 | cifs_dbg(VFS, "%s: Failed to init sg", __func__); | 3482 | cifs_dbg(VFS, "%s: Failed to init sg\n", __func__); |
| 3399 | rc = -ENOMEM; | 3483 | rc = -ENOMEM; |
| 3400 | goto free_req; | 3484 | goto free_req; |
| 3401 | } | 3485 | } |
| @@ -3403,7 +3487,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
| 3403 | iv_len = crypto_aead_ivsize(tfm); | 3487 | iv_len = crypto_aead_ivsize(tfm); |
| 3404 | iv = kzalloc(iv_len, GFP_KERNEL); | 3488 | iv = kzalloc(iv_len, GFP_KERNEL); |
| 3405 | if (!iv) { | 3489 | if (!iv) { |
| 3406 | cifs_dbg(VFS, "%s: Failed to alloc IV", __func__); | 3490 | cifs_dbg(VFS, "%s: Failed to alloc iv\n", __func__); |
| 3407 | rc = -ENOMEM; | 3491 | rc = -ENOMEM; |
| 3408 | goto free_sg; | 3492 | goto free_sg; |
| 3409 | } | 3493 | } |
| @@ -3511,7 +3595,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, | |||
| 3511 | fill_transform_hdr(tr_hdr, orig_len, old_rq); | 3595 | fill_transform_hdr(tr_hdr, orig_len, old_rq); |
| 3512 | 3596 | ||
| 3513 | rc = crypt_message(server, num_rqst, new_rq, 1); | 3597 | rc = crypt_message(server, num_rqst, new_rq, 1); |
| 3514 | cifs_dbg(FYI, "encrypt message returned %d", rc); | 3598 | cifs_dbg(FYI, "Encrypt message returned %d\n", rc); |
| 3515 | if (rc) | 3599 | if (rc) |
| 3516 | goto err_free; | 3600 | goto err_free; |
| 3517 | 3601 | ||
| @@ -3552,7 +3636,7 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, | |||
| 3552 | rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE; | 3636 | rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE; |
| 3553 | 3637 | ||
| 3554 | rc = crypt_message(server, 1, &rqst, 0); | 3638 | rc = crypt_message(server, 1, &rqst, 0); |
| 3555 | cifs_dbg(FYI, "decrypt message returned %d\n", rc); | 3639 | cifs_dbg(FYI, "Decrypt message returned %d\n", rc); |
| 3556 | 3640 | ||
| 3557 | if (rc) | 3641 | if (rc) |
| 3558 | return rc; | 3642 | return rc; |
| @@ -4166,6 +4250,7 @@ struct smb_version_operations smb20_operations = { | |||
| 4166 | .ioctl_query_info = smb2_ioctl_query_info, | 4250 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4167 | .make_node = smb2_make_node, | 4251 | .make_node = smb2_make_node, |
| 4168 | .fiemap = smb3_fiemap, | 4252 | .fiemap = smb3_fiemap, |
| 4253 | .llseek = smb3_llseek, | ||
| 4169 | }; | 4254 | }; |
| 4170 | 4255 | ||
| 4171 | struct smb_version_operations smb21_operations = { | 4256 | struct smb_version_operations smb21_operations = { |
| @@ -4266,6 +4351,7 @@ struct smb_version_operations smb21_operations = { | |||
| 4266 | .ioctl_query_info = smb2_ioctl_query_info, | 4351 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4267 | .make_node = smb2_make_node, | 4352 | .make_node = smb2_make_node, |
| 4268 | .fiemap = smb3_fiemap, | 4353 | .fiemap = smb3_fiemap, |
| 4354 | .llseek = smb3_llseek, | ||
| 4269 | }; | 4355 | }; |
| 4270 | 4356 | ||
| 4271 | struct smb_version_operations smb30_operations = { | 4357 | struct smb_version_operations smb30_operations = { |
| @@ -4375,6 +4461,7 @@ struct smb_version_operations smb30_operations = { | |||
| 4375 | .ioctl_query_info = smb2_ioctl_query_info, | 4461 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4376 | .make_node = smb2_make_node, | 4462 | .make_node = smb2_make_node, |
| 4377 | .fiemap = smb3_fiemap, | 4463 | .fiemap = smb3_fiemap, |
| 4464 | .llseek = smb3_llseek, | ||
| 4378 | }; | 4465 | }; |
| 4379 | 4466 | ||
| 4380 | struct smb_version_operations smb311_operations = { | 4467 | struct smb_version_operations smb311_operations = { |
| @@ -4485,6 +4572,7 @@ struct smb_version_operations smb311_operations = { | |||
| 4485 | .ioctl_query_info = smb2_ioctl_query_info, | 4572 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4486 | .make_node = smb2_make_node, | 4573 | .make_node = smb2_make_node, |
| 4487 | .fiemap = smb3_fiemap, | 4574 | .fiemap = smb3_fiemap, |
| 4575 | .llseek = smb3_llseek, | ||
| 4488 | }; | 4576 | }; |
| 4489 | 4577 | ||
| 4490 | struct smb_version_values smb20_values = { | 4578 | struct smb_version_values smb20_values = { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 29f011d8d8e2..710ceb875161 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -2538,11 +2538,25 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
| 2538 | struct kvec *iov = rqst->rq_iov; | 2538 | struct kvec *iov = rqst->rq_iov; |
| 2539 | unsigned int total_len; | 2539 | unsigned int total_len; |
| 2540 | int rc; | 2540 | int rc; |
| 2541 | char *in_data_buf; | ||
| 2541 | 2542 | ||
| 2542 | rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); | 2543 | rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); |
| 2543 | if (rc) | 2544 | if (rc) |
| 2544 | return rc; | 2545 | return rc; |
| 2545 | 2546 | ||
| 2547 | if (indatalen) { | ||
| 2548 | /* | ||
| 2549 | * indatalen is usually small at a couple of bytes max, so | ||
| 2550 | * just allocate through generic pool | ||
| 2551 | */ | ||
| 2552 | in_data_buf = kmalloc(indatalen, GFP_NOFS); | ||
| 2553 | if (!in_data_buf) { | ||
| 2554 | cifs_small_buf_release(req); | ||
| 2555 | return -ENOMEM; | ||
| 2556 | } | ||
| 2557 | memcpy(in_data_buf, in_data, indatalen); | ||
| 2558 | } | ||
| 2559 | |||
| 2546 | req->CtlCode = cpu_to_le32(opcode); | 2560 | req->CtlCode = cpu_to_le32(opcode); |
| 2547 | req->PersistentFileId = persistent_fid; | 2561 | req->PersistentFileId = persistent_fid; |
| 2548 | req->VolatileFileId = volatile_fid; | 2562 | req->VolatileFileId = volatile_fid; |
| @@ -2563,7 +2577,7 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
| 2563 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); | 2577 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); |
| 2564 | rqst->rq_nvec = 2; | 2578 | rqst->rq_nvec = 2; |
| 2565 | iov[0].iov_len = total_len - 1; | 2579 | iov[0].iov_len = total_len - 1; |
| 2566 | iov[1].iov_base = in_data; | 2580 | iov[1].iov_base = in_data_buf; |
| 2567 | iov[1].iov_len = indatalen; | 2581 | iov[1].iov_len = indatalen; |
| 2568 | } else { | 2582 | } else { |
| 2569 | rqst->rq_nvec = 1; | 2583 | rqst->rq_nvec = 1; |
| @@ -2605,8 +2619,11 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
| 2605 | void | 2619 | void |
| 2606 | SMB2_ioctl_free(struct smb_rqst *rqst) | 2620 | SMB2_ioctl_free(struct smb_rqst *rqst) |
| 2607 | { | 2621 | { |
| 2608 | if (rqst && rqst->rq_iov) | 2622 | if (rqst && rqst->rq_iov) { |
| 2609 | cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ | 2623 | cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
| 2624 | if (rqst->rq_iov[1].iov_len) | ||
| 2625 | kfree(rqst->rq_iov[1].iov_base); | ||
| 2626 | } | ||
| 2610 | } | 2627 | } |
| 2611 | 2628 | ||
| 2612 | 2629 | ||
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index 251ef1223206..caac37b1de8c 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c | |||
| @@ -903,7 +903,7 @@ static int smbd_create_header(struct smbd_connection *info, | |||
| 903 | request->sge[0].addr = ib_dma_map_single(info->id->device, | 903 | request->sge[0].addr = ib_dma_map_single(info->id->device, |
| 904 | (void *)packet, | 904 | (void *)packet, |
| 905 | header_length, | 905 | header_length, |
| 906 | DMA_BIDIRECTIONAL); | 906 | DMA_TO_DEVICE); |
| 907 | if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { | 907 | if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { |
| 908 | mempool_free(request, info->request_mempool); | 908 | mempool_free(request, info->request_mempool); |
| 909 | rc = -EIO; | 909 | rc = -EIO; |
| @@ -1005,7 +1005,7 @@ static int smbd_post_send_sgl(struct smbd_connection *info, | |||
| 1005 | for_each_sg(sgl, sg, num_sgs, i) { | 1005 | for_each_sg(sgl, sg, num_sgs, i) { |
| 1006 | request->sge[i+1].addr = | 1006 | request->sge[i+1].addr = |
| 1007 | ib_dma_map_page(info->id->device, sg_page(sg), | 1007 | ib_dma_map_page(info->id->device, sg_page(sg), |
| 1008 | sg->offset, sg->length, DMA_BIDIRECTIONAL); | 1008 | sg->offset, sg->length, DMA_TO_DEVICE); |
| 1009 | if (ib_dma_mapping_error( | 1009 | if (ib_dma_mapping_error( |
| 1010 | info->id->device, request->sge[i+1].addr)) { | 1010 | info->id->device, request->sge[i+1].addr)) { |
| 1011 | rc = -EIO; | 1011 | rc = -EIO; |
| @@ -2110,8 +2110,10 @@ int smbd_send(struct TCP_Server_Info *server, | |||
| 2110 | goto done; | 2110 | goto done; |
| 2111 | } | 2111 | } |
| 2112 | 2112 | ||
| 2113 | rqst_idx = 0; | 2113 | log_write(INFO, "num_rqst=%d total length=%u\n", |
| 2114 | num_rqst, remaining_data_length); | ||
| 2114 | 2115 | ||
| 2116 | rqst_idx = 0; | ||
| 2115 | next_rqst: | 2117 | next_rqst: |
| 2116 | rqst = &rqst_array[rqst_idx]; | 2118 | rqst = &rqst_array[rqst_idx]; |
| 2117 | iov = rqst->rq_iov; | 2119 | iov = rqst->rq_iov; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 9a16ff4b9f5e..60661b3f983a 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #include <linux/uaccess.h> | 33 | #include <linux/uaccess.h> |
| 34 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
| 35 | #include <linux/mempool.h> | 35 | #include <linux/mempool.h> |
| 36 | #include <linux/signal.h> | 36 | #include <linux/sched/signal.h> |
| 37 | #include "cifspdu.h" | 37 | #include "cifspdu.h" |
| 38 | #include "cifsglob.h" | 38 | #include "cifsglob.h" |
| 39 | #include "cifsproto.h" | 39 | #include "cifsproto.h" |
