diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2012-07-12 10:30:44 -0400 |
---|---|---|
committer | Pavel Shilovsky <pshilovsky@samba.org> | 2012-07-24 13:55:17 -0400 |
commit | 9094fad1ed90caebd25b1bdec3c8982d079356ee (patch) | |
tree | a6a111f572f18533d31d80a771fe848507cb26b6 /fs/cifs | |
parent | f6d7617862e106affc59c6933099e45629af5c4e (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.h | 3 | ||||
-rw-r--r-- | fs/cifs/connect.c | 3 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 8 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 49 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 12 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 1 |
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 | |||
62 | extern mempool_t *cifs_req_poolp; | 59 | extern 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 | ||
210 | static bool | ||
211 | smb2_can_echo(struct TCP_Server_Info *server) | ||
212 | { | ||
213 | return server->echoes; | ||
214 | } | ||
215 | |||
210 | struct smb_version_operations smb21_operations = { | 216 | struct 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 | */ | ||
1085 | static void | ||
1086 | smb2_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 | |||
1099 | int | ||
1100 | SMB2_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 | ||
451 | struct smb2_echo_req { | ||
452 | struct smb2_hdr hdr; | ||
453 | __le16 StructureSize; /* Must be 4 */ | ||
454 | __u16 Reserved; | ||
455 | } __packed; | ||
456 | |||
457 | struct 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, | |||
73 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, | 73 | extern 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); |
76 | extern int SMB2_echo(struct TCP_Server_Info *server); | ||
76 | 77 | ||
77 | #endif /* _SMB2PROTO_H */ | 78 | #endif /* _SMB2PROTO_H */ |