CIFS: Add echo request support for SMB2
authorPavel Shilovsky <pshilovsky@samba.org>
Thu, 12 Jul 2012 14:30:44 +0000 (18:30 +0400)
committerPavel Shilovsky <pshilovsky@samba.org>
Tue, 24 Jul 2012 17:55:17 +0000 (21:55 +0400)
Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2proto.h

index 0c53a83392536e10da3bab228f0afe77892a8e3f..ae9a1e900c1582e39c2558b9d6e30dfd2736c10b 100644 (file)
@@ -73,6 +73,9 @@
 /*           (max path length + 1 for null) * 2 for unicode    */
 #define MAX_NAME 514
 
+/* SMB echo "timeout" -- FIXME: tunable? */
+#define SMB_ECHO_INTERVAL (60 * HZ)
+
 #include "cifspdu.h"
 
 #ifndef XATTR_DOS_ATTRIB
index a83ed766aa945d8533506708905f9d475858a3ec..5ab173fd63391d7c9fa129bcb0ef3e5542c969a4 100644 (file)
@@ -56,9 +56,6 @@
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
 
-/* SMB echo "timeout" -- FIXME: tunable? */
-#define SMB_ECHO_INTERVAL (60 * HZ)
-
 extern mempool_t *cifs_req_poolp;
 
 /* FIXME: should these be tunable? */
index 8672e49d1c4c7a803bca230ddc700bc8167327c8..483bd0ba2ecb881c178510824c46e7a7efe9f76d 100644 (file)
@@ -207,6 +207,12 @@ smb2_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
        return NULL;
 }
 
+static bool
+smb2_can_echo(struct TCP_Server_Info *server)
+{
+       return server->echoes;
+}
+
 struct smb_version_operations smb21_operations = {
        .setup_request = smb2_setup_request,
        .setup_async_request = smb2_setup_async_request,
@@ -226,6 +232,8 @@ struct smb_version_operations smb21_operations = {
        .tree_connect = SMB2_tcon,
        .tree_disconnect = SMB2_tdis,
        .is_path_accessible = smb2_is_path_accessible,
+       .can_echo = smb2_can_echo,
+       .echo = SMB2_echo,
        .query_path_info = smb2_query_path_info,
        .get_srv_inum = smb2_get_srv_inum,
        .build_path_to_root = smb2_build_path_to_root,
index 7ef5324786a6de37a59a3e906a71279e271da83e..373b6945161fd7d9563ba51f76323e865a455239 100644 (file)
@@ -1074,3 +1074,52 @@ qinf_exit:
        free_rsp_buf(resp_buftype, rsp);
        return rc;
 }
+
+/*
+ * This is a no-op for now. We're not really interested in the reply, but
+ * rather in the fact that the server sent one and that server->lstrp
+ * gets updated.
+ *
+ * FIXME: maybe we should consider checking that the reply matches request?
+ */
+static void
+smb2_echo_callback(struct mid_q_entry *mid)
+{
+       struct TCP_Server_Info *server = mid->callback_data;
+       struct smb2_echo_rsp *smb2 = (struct smb2_echo_rsp *)mid->resp_buf;
+       unsigned int credits_received = 1;
+
+       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+               credits_received = le16_to_cpu(smb2->hdr.CreditRequest);
+
+       DeleteMidQEntry(mid);
+       add_credits(server, credits_received, CIFS_ECHO_OP);
+}
+
+int
+SMB2_echo(struct TCP_Server_Info *server)
+{
+       struct smb2_echo_req *req;
+       int rc = 0;
+       struct kvec iov;
+
+       cFYI(1, "In echo request");
+
+       rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
+       if (rc)
+               return rc;
+
+       req->hdr.CreditRequest = cpu_to_le16(1);
+
+       iov.iov_base = (char *)req;
+       /* 4 for rfc1002 length field */
+       iov.iov_len = get_rfc1002_length(req) + 4;
+
+       rc = cifs_call_async(server, &iov, 1, NULL, smb2_echo_callback, server,
+                            CIFS_ECHO_OP);
+       if (rc)
+               cFYI(1, "Echo request failed: %d", rc);
+
+       cifs_small_buf_release(req);
+       return rc;
+}
index 9151e9040b023a08bb8e968e1d59ce48b2744fdd..59aae608d3662b15a19f43d7bab2870f8ba4d66c 100644 (file)
@@ -448,6 +448,18 @@ struct smb2_close_rsp {
        __le32 Attributes;
 } __packed;
 
+struct smb2_echo_req {
+       struct smb2_hdr hdr;
+       __le16 StructureSize;   /* Must be 4 */
+       __u16  Reserved;
+} __packed;
+
+struct smb2_echo_rsp {
+       struct smb2_hdr hdr;
+       __le16 StructureSize;   /* Must be 4 */
+       __u16  Reserved;
+} __packed;
+
 /* Possible InfoType values */
 #define SMB2_O_INFO_FILE       0x01
 #define SMB2_O_INFO_FILESYSTEM 0x02
index 1a17955c35c949d88575276a33b06ffbf33eb2bc..902bbe2b5ad37724987a2d0bec22e2dc49664312 100644 (file)
@@ -73,5 +73,6 @@ extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
                           u64 persistent_file_id, u64 volatile_file_id,
                           struct smb2_file_all_info *data);
+extern int SMB2_echo(struct TCP_Server_Info *server);
 
 #endif                 /* _SMB2PROTO_H */