aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@samba.org>2012-07-12 10:30:44 -0400
committerPavel Shilovsky <pshilovsky@samba.org>2012-07-24 13:55:17 -0400
commit9094fad1ed90caebd25b1bdec3c8982d079356ee (patch)
treea6a111f572f18533d31d80a771fe848507cb26b6 /fs/cifs
parentf6d7617862e106affc59c6933099e45629af5c4e (diff)
CIFS: Add echo request support for SMB2
Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/smb2ops.c8
-rw-r--r--fs/cifs/smb2pdu.c49
-rw-r--r--fs/cifs/smb2pdu.h12
-rw-r--r--fs/cifs/smb2proto.h1
6 files changed, 73 insertions, 3 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 0c53a8339253..ae9a1e900c15 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -73,6 +73,9 @@
73/* (max path length + 1 for null) * 2 for unicode */ 73/* (max path length + 1 for null) * 2 for unicode */
74#define MAX_NAME 514 74#define MAX_NAME 514
75 75
76/* SMB echo "timeout" -- FIXME: tunable? */
77#define SMB_ECHO_INTERVAL (60 * HZ)
78
76#include "cifspdu.h" 79#include "cifspdu.h"
77 80
78#ifndef XATTR_DOS_ATTRIB 81#ifndef XATTR_DOS_ATTRIB
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a83ed766aa94..5ab173fd6339 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -56,9 +56,6 @@
56#define CIFS_PORT 445 56#define CIFS_PORT 445
57#define RFC1001_PORT 139 57#define RFC1001_PORT 139
58 58
59/* SMB echo "timeout" -- FIXME: tunable? */
60#define SMB_ECHO_INTERVAL (60 * HZ)
61
62extern mempool_t *cifs_req_poolp; 59extern mempool_t *cifs_req_poolp;
63 60
64/* FIXME: should these be tunable? */ 61/* FIXME: should these be tunable? */
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 8672e49d1c4c..483bd0ba2ecb 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -207,6 +207,12 @@ smb2_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
207 return NULL; 207 return NULL;
208} 208}
209 209
210static bool
211smb2_can_echo(struct TCP_Server_Info *server)
212{
213 return server->echoes;
214}
215
210struct smb_version_operations smb21_operations = { 216struct smb_version_operations smb21_operations = {
211 .setup_request = smb2_setup_request, 217 .setup_request = smb2_setup_request,
212 .setup_async_request = smb2_setup_async_request, 218 .setup_async_request = smb2_setup_async_request,
@@ -226,6 +232,8 @@ struct smb_version_operations smb21_operations = {
226 .tree_connect = SMB2_tcon, 232 .tree_connect = SMB2_tcon,
227 .tree_disconnect = SMB2_tdis, 233 .tree_disconnect = SMB2_tdis,
228 .is_path_accessible = smb2_is_path_accessible, 234 .is_path_accessible = smb2_is_path_accessible,
235 .can_echo = smb2_can_echo,
236 .echo = SMB2_echo,
229 .query_path_info = smb2_query_path_info, 237 .query_path_info = smb2_query_path_info,
230 .get_srv_inum = smb2_get_srv_inum, 238 .get_srv_inum = smb2_get_srv_inum,
231 .build_path_to_root = smb2_build_path_to_root, 239 .build_path_to_root = smb2_build_path_to_root,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 7ef5324786a6..373b6945161f 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1074,3 +1074,52 @@ qinf_exit:
1074 free_rsp_buf(resp_buftype, rsp); 1074 free_rsp_buf(resp_buftype, rsp);
1075 return rc; 1075 return rc;
1076} 1076}
1077
1078/*
1079 * This is a no-op for now. We're not really interested in the reply, but
1080 * rather in the fact that the server sent one and that server->lstrp
1081 * gets updated.
1082 *
1083 * FIXME: maybe we should consider checking that the reply matches request?
1084 */
1085static void
1086smb2_echo_callback(struct mid_q_entry *mid)
1087{
1088 struct TCP_Server_Info *server = mid->callback_data;
1089 struct smb2_echo_rsp *smb2 = (struct smb2_echo_rsp *)mid->resp_buf;
1090 unsigned int credits_received = 1;
1091
1092 if (mid->mid_state == MID_RESPONSE_RECEIVED)
1093 credits_received = le16_to_cpu(smb2->hdr.CreditRequest);
1094
1095 DeleteMidQEntry(mid);
1096 add_credits(server, credits_received, CIFS_ECHO_OP);
1097}
1098
1099int
1100SMB2_echo(struct TCP_Server_Info *server)
1101{
1102 struct smb2_echo_req *req;
1103 int rc = 0;
1104 struct kvec iov;
1105
1106 cFYI(1, "In echo request");
1107
1108 rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
1109 if (rc)
1110 return rc;
1111
1112 req->hdr.CreditRequest = cpu_to_le16(1);
1113
1114 iov.iov_base = (char *)req;
1115 /* 4 for rfc1002 length field */
1116 iov.iov_len = get_rfc1002_length(req) + 4;
1117
1118 rc = cifs_call_async(server, &iov, 1, NULL, smb2_echo_callback, server,
1119 CIFS_ECHO_OP);
1120 if (rc)
1121 cFYI(1, "Echo request failed: %d", rc);
1122
1123 cifs_small_buf_release(req);
1124 return rc;
1125}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 9151e9040b02..59aae608d366 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -448,6 +448,18 @@ struct smb2_close_rsp {
448 __le32 Attributes; 448 __le32 Attributes;
449} __packed; 449} __packed;
450 450
451struct smb2_echo_req {
452 struct smb2_hdr hdr;
453 __le16 StructureSize; /* Must be 4 */
454 __u16 Reserved;
455} __packed;
456
457struct smb2_echo_rsp {
458 struct smb2_hdr hdr;
459 __le16 StructureSize; /* Must be 4 */
460 __u16 Reserved;
461} __packed;
462
451/* Possible InfoType values */ 463/* Possible InfoType values */
452#define SMB2_O_INFO_FILE 0x01 464#define SMB2_O_INFO_FILE 0x01
453#define SMB2_O_INFO_FILESYSTEM 0x02 465#define SMB2_O_INFO_FILESYSTEM 0x02
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 1a17955c35c9..902bbe2b5ad3 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -73,5 +73,6 @@ extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
73extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, 73extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
74 u64 persistent_file_id, u64 volatile_file_id, 74 u64 persistent_file_id, u64 volatile_file_id,
75 struct smb2_file_all_info *data); 75 struct smb2_file_all_info *data);
76extern int SMB2_echo(struct TCP_Server_Info *server);
76 77
77#endif /* _SMB2PROTO_H */ 78#endif /* _SMB2PROTO_H */