smb2ops.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * SMB2 version specific operations
  3. *
  4. * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License v2 as published
  8. * by the Free Software Foundation.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  13. * the GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "cifsglob.h"
  20. #include "smb2pdu.h"
  21. #include "smb2proto.h"
  22. #include "cifsproto.h"
  23. #include "cifs_debug.h"
  24. static int
  25. change_conf(struct TCP_Server_Info *server)
  26. {
  27. server->credits += server->echo_credits + server->oplock_credits;
  28. server->oplock_credits = server->echo_credits = 0;
  29. switch (server->credits) {
  30. case 0:
  31. return -1;
  32. case 1:
  33. server->echoes = false;
  34. server->oplocks = false;
  35. cERROR(1, "disabling echoes and oplocks");
  36. break;
  37. case 2:
  38. server->echoes = true;
  39. server->oplocks = false;
  40. server->echo_credits = 1;
  41. cFYI(1, "disabling oplocks");
  42. break;
  43. default:
  44. server->echoes = true;
  45. server->oplocks = true;
  46. server->echo_credits = 1;
  47. server->oplock_credits = 1;
  48. }
  49. server->credits -= server->echo_credits + server->oplock_credits;
  50. return 0;
  51. }
  52. static void
  53. smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
  54. const int optype)
  55. {
  56. int *val, rc = 0;
  57. spin_lock(&server->req_lock);
  58. val = server->ops->get_credits_field(server, optype);
  59. *val += add;
  60. server->in_flight--;
  61. if (server->in_flight == 0)
  62. rc = change_conf(server);
  63. spin_unlock(&server->req_lock);
  64. wake_up(&server->request_q);
  65. if (rc)
  66. cifs_reconnect(server);
  67. }
  68. static void
  69. smb2_set_credits(struct TCP_Server_Info *server, const int val)
  70. {
  71. spin_lock(&server->req_lock);
  72. server->credits = val;
  73. spin_unlock(&server->req_lock);
  74. }
  75. static int *
  76. smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
  77. {
  78. switch (optype) {
  79. case CIFS_ECHO_OP:
  80. return &server->echo_credits;
  81. case CIFS_OBREAK_OP:
  82. return &server->oplock_credits;
  83. default:
  84. return &server->credits;
  85. }
  86. }
  87. static unsigned int
  88. smb2_get_credits(struct mid_q_entry *mid)
  89. {
  90. return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
  91. }
  92. static __u64
  93. smb2_get_next_mid(struct TCP_Server_Info *server)
  94. {
  95. __u64 mid;
  96. /* for SMB2 we need the current value */
  97. spin_lock(&GlobalMid_Lock);
  98. mid = server->CurrentMid++;
  99. spin_unlock(&GlobalMid_Lock);
  100. return mid;
  101. }
  102. struct smb_version_operations smb21_operations = {
  103. .setup_request = smb2_setup_request,
  104. .check_receive = smb2_check_receive,
  105. .add_credits = smb2_add_credits,
  106. .set_credits = smb2_set_credits,
  107. .get_credits_field = smb2_get_credits_field,
  108. .get_credits = smb2_get_credits,
  109. .get_next_mid = smb2_get_next_mid,
  110. };
  111. struct smb_version_values smb21_values = {
  112. .version_string = SMB21_VERSION_STRING,
  113. .lock_cmd = SMB2_LOCK,
  114. };