All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] Get SMB2 mount work
@ 2012-06-19 12:39 Pavel Shilovsky
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  0 siblings, 1 reply; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

This is the first chunk of SMB2 patches. It allows:
1) mount a network share,
2) stat inode information,
3) send echo message,
4) display statistics.

The patchset implements the approach of having ops structure of
protocol-specific callbacks that is used by the generic code.

Pavel Shilovsky (21):
  CIFS: Add SMB2 status codes
  CIFS: Make transport routines work with SMB2
  CIFS: Add SMB2 credits support
  CIFS: Make demultiplex_thread work with SMB2 code
  CIFS: Respect SMB2 header/max header size
  CIFS: Add capability to send SMB2 negotiate message
  CIFS: Add session setup/logoff capability for SMB2
  CIFS: Add tree connect/disconnect capability for SMB2
  CIFS: Process reconnects for SMB2 shares
  CIFS: Move getting dfs referalls to ops struct
  CIFS: Move informational tcon calls to ops struct
  CIFS: Move is_path_accessible to ops struct
  CIFS: Add SMB2 support for is_path_accessible
  CIFS: Move query inode info code to ops struct
  CIFS: Query SMB2 inode info
  CIFS: Move building path to root to ops struct
  CIFS: Add SMB2 support for build_path_to_root
  CIFS: Move echo code to osp struct
  CIFS: Add echo request support for SMB2
  CIFS: Move clear/print_stats code to ops struct
  CIFS: Allow SMB2 statistics to be tracked

Steve French (1):
  CIFS: Map SMB2 status codes to POSIX errors

 fs/cifs/Makefile        |    3 +-
 fs/cifs/cifs_debug.c    |   62 +--
 fs/cifs/cifs_unicode.c  |   60 ++
 fs/cifs/cifs_unicode.h  |    6 +-
 fs/cifs/cifsfs.c        |   18 +-
 fs/cifs/cifsglob.h      |  126 +++-
 fs/cifs/cifsproto.h     |   23 +-
 fs/cifs/cifssmb.c       |   78 ++-
 fs/cifs/connect.c       |  111 ++--
 fs/cifs/inode.c         |  124 +---
 fs/cifs/misc.c          |   27 +-
 fs/cifs/ntlmssp.h       |   10 +
 fs/cifs/sess.c          |    6 +-
 fs/cifs/smb1ops.c       |  197 +++++
 fs/cifs/smb2glob.h      |   44 ++
 fs/cifs/smb2inode.c     |  124 ++++
 fs/cifs/smb2maperror.c  | 1830 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2misc.c      |  344 +++++++++
 fs/cifs/smb2ops.c       |  299 ++++++++
 fs/cifs/smb2pdu.c       | 1127 +++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.h       |  568 +++++++++++++++
 fs/cifs/smb2proto.h     |   75 ++
 fs/cifs/smb2status.h    | 1782 +++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2transport.c |  151 ++++
 fs/cifs/transport.c     |   13 +-
 25 files changed, 6905 insertions(+), 303 deletions(-)
 create mode 100644 fs/cifs/smb2glob.h
 create mode 100644 fs/cifs/smb2inode.c
 create mode 100644 fs/cifs/smb2maperror.c
 create mode 100644 fs/cifs/smb2misc.c
 create mode 100644 fs/cifs/smb2pdu.c
 create mode 100644 fs/cifs/smb2pdu.h
 create mode 100644 fs/cifs/smb2proto.h
 create mode 100644 fs/cifs/smb2status.h
 create mode 100644 fs/cifs/smb2transport.c

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/22] CIFS: Add SMB2 status codes
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2012-06-19 12:39   ` Pavel Shilovsky
       [not found]     ` <1340109611-7210-2-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2012-06-19 12:39   ` [PATCH 03/22] CIFS: Make transport routines work with SMB2 Pavel Shilovsky
                     ` (19 subsequent siblings)
  20 siblings, 1 reply; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/smb2status.h | 1782 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1782 insertions(+), 0 deletions(-)
 create mode 100644 fs/cifs/smb2status.h

diff --git a/fs/cifs/smb2status.h b/fs/cifs/smb2status.h
new file mode 100644
index 0000000..d4edf05
--- /dev/null
+++ b/fs/cifs/smb2status.h
@@ -0,0 +1,1782 @@
+/*
+ *   fs/cifs/smb2status.h
+ *
+ *   SMB2 Status code (network error) definitions
+ *   Definitions are from MS-ERREF
+ *
+ *   Copyright (c) International Business Machines  Corp., 2009,2011
+ *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ *  0 1 2 3 4 5 6 7 8 9 0 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ *  SEV C N <-------Facility--------> <------Error Status Code------>
+ *
+ *  C is set if "customer defined" error, N bit is reserved and MBZ
+ */
+
+#define STATUS_SEVERITY_SUCCESS       cpu_to_le32 0x0000
+#define STATUS_SEVERITY_INFORMATIONAL cpu_to_le32 0x0001
+#define STATUS_SEVERITY_WARNING       cpu_to_le32 0x0002
+#define STATUS_SEVERITY_ERROR         cpu_to_le32 0x0003
+
+struct ntstatus {
+	/* Facility is the high 12 bits of the following field */
+	__le32 Facility; /* low 2 bits Severity, next is Customer, then rsrvd */
+	__le32 Code;
+};
+
+#define STATUS_SUCCESS	 0x00000000
+#define STATUS_WAIT_0	 0x00000000
+#define STATUS_WAIT_1	 0x00000001
+#define STATUS_WAIT_2	 0x00000002
+#define STATUS_WAIT_3	 0x00000003
+#define STATUS_WAIT_63	 0x0000003F
+#define STATUS_ABANDONED	 0x00000080
+#define STATUS_ABANDONED_WAIT_0	 0x00000080
+#define STATUS_ABANDONED_WAIT_63	 0x000000BF
+#define STATUS_USER_APC	 0x000000C0
+#define STATUS_KERNEL_APC	 0x00000100
+#define STATUS_ALERTED	 0x00000101
+#define STATUS_TIMEOUT	 0x00000102
+#define STATUS_PENDING	 0x00000103
+#define STATUS_REPARSE	 0x00000104
+/* #define STATUS_MORE_ENTRIES	 0x00000105 */
+#define STATUS_NOT_ALL_ASSIGNED	 0x00000106
+#define STATUS_SOME_NOT_MAPPED	 0x00000107
+#define STATUS_OPLOCK_BREAK_IN_PROGRESS	 0x00000108
+#define STATUS_VOLUME_MOUNTED	 0x00000109
+#define STATUS_RXACT_COMMITTED	 0x0000010A
+#define STATUS_NOTIFY_CLEANUP	 0x0000010B
+/* #define STATUS_NOTIFY_ENUM_DIR	 0x0000010C */
+#define STATUS_NO_QUOTAS_FOR_ACCOUNT	 0x0000010D
+#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED	 0x0000010E
+#define STATUS_PAGE_FAULT_TRANSITION	 0x00000110
+#define STATUS_PAGE_FAULT_DEMAND_ZERO	 0x00000111
+#define STATUS_PAGE_FAULT_COPY_ON_WRITE	 0x00000112
+#define STATUS_PAGE_FAULT_GUARD_PAGE	 0x00000113
+#define STATUS_PAGE_FAULT_PAGING_FILE	 0x00000114
+#define STATUS_CACHE_PAGE_LOCKED	 0x00000115
+#define STATUS_CRASH_DUMP	 0x00000116
+#define STATUS_BUFFER_ALL_ZEROS	 0x00000117
+#define STATUS_REPARSE_OBJECT	 0x00000118
+#define STATUS_RESOURCE_REQUIREMENTS_CHANGED	0x00000119
+#define STATUS_TRANSLATION_COMPLETE	 0x00000120
+#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY	0x00000121
+#define STATUS_NOTHING_TO_TERMINATE	 0x00000122
+#define STATUS_PROCESS_NOT_IN_JOB	 0x00000123
+#define STATUS_PROCESS_IN_JOB	 0x00000124
+#define STATUS_VOLSNAP_HIBERNATE_READY	 0x00000125
+#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY	0x00000126
+#define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED	0x00000127
+#define STATUS_INTERRUPT_STILL_CONNECTED	0x00000128
+#define STATUS_PROCESS_CLONED	 0x00000129
+#define STATUS_FILE_LOCKED_WITH_ONLY_READERS	0x0000012A
+#define STATUS_FILE_LOCKED_WITH_WRITERS	 0x0000012B
+#define STATUS_RESOURCEMANAGER_READ_ONLY	0x00000202
+#define STATUS_WAIT_FOR_OPLOCK	 0x00000367
+#define DBG_EXCEPTION_HANDLED	 0x00010001
+#define DBG_CONTINUE	 0x00010002
+#define STATUS_FLT_IO_COMPLETE	 0x001C0001
+#define STATUS_OBJECT_NAME_EXISTS	 0x40000000
+#define STATUS_THREAD_WAS_SUSPENDED	 0x40000001
+#define STATUS_WORKING_SET_LIMIT_RANGE	 0x40000002
+#define STATUS_IMAGE_NOT_AT_BASE	 0x40000003
+#define STATUS_RXACT_STATE_CREATED	 0x40000004
+#define STATUS_SEGMENT_NOTIFICATION	 0x40000005
+#define STATUS_LOCAL_USER_SESSION_KEY	 0x40000006
+#define STATUS_BAD_CURRENT_DIRECTORY	 0x40000007
+#define STATUS_SERIAL_MORE_WRITES	 0x40000008
+#define STATUS_REGISTRY_RECOVERED	 0x40000009
+#define STATUS_FT_READ_RECOVERY_FROM_BACKUP	 0x4000000A
+#define STATUS_FT_WRITE_RECOVERY	 0x4000000B
+#define STATUS_SERIAL_COUNTER_TIMEOUT	 0x4000000C
+#define STATUS_NULL_LM_PASSWORD	 0x4000000D
+#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH	 0x4000000E
+#define STATUS_RECEIVE_PARTIAL	 0x4000000F
+#define STATUS_RECEIVE_EXPEDITED	 0x40000010
+#define STATUS_RECEIVE_PARTIAL_EXPEDITED	 0x40000011
+#define STATUS_EVENT_DONE	 0x40000012
+#define STATUS_EVENT_PENDING	 0x40000013
+#define STATUS_CHECKING_FILE_SYSTEM	 0x40000014
+#define STATUS_FATAL_APP_EXIT	 0x40000015
+#define STATUS_PREDEFINED_HANDLE	 0x40000016
+#define STATUS_WAS_UNLOCKED	 0x40000017
+#define STATUS_SERVICE_NOTIFICATION	 0x40000018
+#define STATUS_WAS_LOCKED	 0x40000019
+#define STATUS_LOG_HARD_ERROR	 0x4000001A
+#define STATUS_ALREADY_WIN32	 0x4000001B
+#define STATUS_WX86_UNSIMULATE	 0x4000001C
+#define STATUS_WX86_CONTINUE	 0x4000001D
+#define STATUS_WX86_SINGLE_STEP	 0x4000001E
+#define STATUS_WX86_BREAKPOINT	 0x4000001F
+#define STATUS_WX86_EXCEPTION_CONTINUE	 0x40000020
+#define STATUS_WX86_EXCEPTION_LASTCHANCE	0x40000021
+#define STATUS_WX86_EXCEPTION_CHAIN	 0x40000022
+#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE	0x40000023
+#define STATUS_NO_YIELD_PERFORMED	 0x40000024
+#define STATUS_TIMER_RESUME_IGNORED	 0x40000025
+#define STATUS_ARBITRATION_UNHANDLED	 0x40000026
+#define STATUS_CARDBUS_NOT_SUPPORTED	 0x40000027
+#define STATUS_WX86_CREATEWX86TIB	 0x40000028
+#define STATUS_MP_PROCESSOR_MISMATCH	 0x40000029
+#define STATUS_HIBERNATED	 0x4000002A
+#define STATUS_RESUME_HIBERNATION	 0x4000002B
+#define STATUS_FIRMWARE_UPDATED	 0x4000002C
+#define STATUS_DRIVERS_LEAKING_LOCKED_PAGES	0x4000002D
+#define STATUS_MESSAGE_RETRIEVED	 0x4000002E
+#define STATUS_SYSTEM_POWERSTATE_TRANSITION	0x4000002F
+#define STATUS_ALPC_CHECK_COMPLETION_LIST	0x40000030
+#define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION	 0x40000031
+#define STATUS_ACCESS_AUDIT_BY_POLICY	 0x40000032
+#define STATUS_ABANDON_HIBERFILE	 0x40000033
+#define STATUS_BIZRULES_NOT_ENABLED	 0x40000034
+#define STATUS_WAKE_SYSTEM	 0x40000294
+#define STATUS_DS_SHUTTING_DOWN	 0x40000370
+#define DBG_REPLY_LATER	 0x40010001
+#define DBG_UNABLE_TO_PROVIDE_HANDLE	 0x40010002
+#define DBG_TERMINATE_THREAD	 0x40010003
+#define DBG_TERMINATE_PROCESS	 0x40010004
+#define DBG_CONTROL_C	 0x40010005
+#define DBG_PRINTEXCEPTION_C	 0x40010006
+#define DBG_RIPEXCEPTION	 0x40010007
+#define DBG_CONTROL_BREAK	 0x40010008
+#define DBG_COMMAND_EXCEPTION	 0x40010009
+#define RPC_NT_UUID_LOCAL_ONLY	 0x40020056
+#define RPC_NT_SEND_INCOMPLETE	 0x400200AF
+#define STATUS_CTX_CDM_CONNECT	 0x400A0004
+#define STATUS_CTX_CDM_DISCONNECT	 0x400A0005
+#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT	0x4015000D
+#define STATUS_RECOVERY_NOT_NEEDED	 0x40190034
+#define STATUS_RM_ALREADY_STARTED	 0x40190035
+#define STATUS_LOG_NO_RESTART	 0x401A000C
+#define STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST	 0x401B00EC
+#define STATUS_GRAPHICS_PARTIAL_DATA_POPULATED	0x401E000A
+#define STATUS_GRAPHICS_DRIVER_MISMATCH	 0x401E0117
+#define STATUS_GRAPHICS_MODE_NOT_PINNED	 0x401E0307
+#define STATUS_GRAPHICS_NO_PREFERRED_MODE	0x401E031E
+#define STATUS_GRAPHICS_DATASET_IS_EMPTY	0x401E034B
+#define STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET	0x401E034C
+#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED	0x401E0351
+#define STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS	 0x401E042F
+#define STATUS_GRAPHICS_LEADLINK_START_DEFERRED	 0x401E0437
+#define STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY	 0x401E0439
+#define STATUS_GRAPHICS_START_DEFERRED	 0x401E043A
+#define STATUS_NDIS_INDICATION_REQUIRED	 0x40230001
+#define STATUS_GUARD_PAGE_VIOLATION	 0x80000001
+#define STATUS_DATATYPE_MISALIGNMENT	 0x80000002
+#define STATUS_BREAKPOINT	 0x80000003
+#define STATUS_SINGLE_STEP	 0x80000004
+/* #define STATUS_BUFFER_OVERFLOW	 0x80000005 */
+#define STATUS_NO_MORE_FILES	 0x80000006
+#define STATUS_WAKE_SYSTEM_DEBUGGER	 0x80000007
+#define STATUS_HANDLES_CLOSED	 0x8000000A
+#define STATUS_NO_INHERITANCE	 0x8000000B
+#define STATUS_GUID_SUBSTITUTION_MADE	 0x8000000C
+#define STATUS_PARTIAL_COPY	 0x8000000D
+#define STATUS_DEVICE_PAPER_EMPTY	 0x8000000E
+#define STATUS_DEVICE_POWERED_OFF	 0x8000000F
+#define STATUS_DEVICE_OFF_LINE	 0x80000010
+#define STATUS_DEVICE_BUSY	 0x80000011
+#define STATUS_NO_MORE_EAS	 0x80000012
+#define STATUS_INVALID_EA_NAME	 0x80000013
+#define STATUS_EA_LIST_INCONSISTENT	 0x80000014
+#define STATUS_INVALID_EA_FLAG	 0x80000015
+#define STATUS_VERIFY_REQUIRED	 0x80000016
+#define STATUS_EXTRANEOUS_INFORMATION	 0x80000017
+#define STATUS_RXACT_COMMIT_NECESSARY	 0x80000018
+#define STATUS_NO_MORE_ENTRIES	 0x8000001A
+#define STATUS_FILEMARK_DETECTED	 0x8000001B
+#define STATUS_MEDIA_CHANGED	 0x8000001C
+#define STATUS_BUS_RESET	 0x8000001D
+#define STATUS_END_OF_MEDIA	 0x8000001E
+#define STATUS_BEGINNING_OF_MEDIA	 0x8000001F
+#define STATUS_MEDIA_CHECK	 0x80000020
+#define STATUS_SETMARK_DETECTED	 0x80000021
+#define STATUS_NO_DATA_DETECTED	 0x80000022
+#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES	 0x80000023
+#define STATUS_SERVER_HAS_OPEN_HANDLES	 0x80000024
+#define STATUS_ALREADY_DISCONNECTED	 0x80000025
+#define STATUS_LONGJUMP	 0x80000026
+#define STATUS_CLEANER_CARTRIDGE_INSTALLED	 0x80000027
+#define STATUS_PLUGPLAY_QUERY_VETOED	 0x80000028
+#define STATUS_UNWIND_CONSOLIDATE	 0x80000029
+#define STATUS_REGISTRY_HIVE_RECOVERED	 0x8000002A
+#define STATUS_DLL_MIGHT_BE_INSECURE	 0x8000002B
+#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE	 0x8000002C
+#define STATUS_STOPPED_ON_SYMLINK	 0x8000002D
+#define STATUS_DEVICE_REQUIRES_CLEANING	 0x80000288
+#define STATUS_DEVICE_DOOR_OPEN	 0x80000289
+#define STATUS_DATA_LOST_REPAIR	 0x80000803
+#define DBG_EXCEPTION_NOT_HANDLED	 0x80010001
+#define STATUS_CLUSTER_NODE_ALREADY_UP	 0x80130001
+#define STATUS_CLUSTER_NODE_ALREADY_DOWN	 0x80130002
+#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE	 0x80130003
+#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE	 0x80130004
+#define STATUS_CLUSTER_NODE_ALREADY_MEMBER	 0x80130005
+#define STATUS_COULD_NOT_RESIZE_LOG	 0x80190009
+#define STATUS_NO_TXF_METADATA	 0x80190029
+#define STATUS_CANT_RECOVER_WITH_HANDLE_OPEN	 0x80190031
+#define STATUS_TXF_METADATA_ALREADY_PRESENT	 0x80190041
+#define STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET	 0x80190042
+#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED	 0x801B00EB
+#define STATUS_FLT_BUFFER_TOO_SMALL	 0x801C0001
+#define STATUS_FVE_PARTIAL_METADATA	 0x80210001
+#define STATUS_UNSUCCESSFUL	 0xC0000001
+#define STATUS_NOT_IMPLEMENTED	 0xC0000002
+#define STATUS_INVALID_INFO_CLASS	 0xC0000003
+#define STATUS_INFO_LENGTH_MISMATCH	 0xC0000004
+#define STATUS_ACCESS_VIOLATION	 0xC0000005
+#define STATUS_IN_PAGE_ERROR	 0xC0000006
+#define STATUS_PAGEFILE_QUOTA	 0xC0000007
+#define STATUS_INVALID_HANDLE	 0xC0000008
+#define STATUS_BAD_INITIAL_STACK	 0xC0000009
+#define STATUS_BAD_INITIAL_PC	 0xC000000A
+#define STATUS_INVALID_CID	 0xC000000B
+#define STATUS_TIMER_NOT_CANCELED	 0xC000000C
+#define STATUS_INVALID_PARAMETER	 0xC000000D
+#define STATUS_NO_SUCH_DEVICE	 0xC000000E
+#define STATUS_NO_SUCH_FILE	 0xC000000F
+#define STATUS_INVALID_DEVICE_REQUEST	 0xC0000010
+#define STATUS_END_OF_FILE	 0xC0000011
+#define STATUS_WRONG_VOLUME	 0xC0000012
+#define STATUS_NO_MEDIA_IN_DEVICE	 0xC0000013
+#define STATUS_UNRECOGNIZED_MEDIA	 0xC0000014
+#define STATUS_NONEXISTENT_SECTOR	 0xC0000015
+#define STATUS_MORE_PROCESSING_REQUIRED	 0xC0000016
+#define STATUS_NO_MEMORY	 0xC0000017
+#define STATUS_CONFLICTING_ADDRESSES	 0xC0000018
+#define STATUS_NOT_MAPPED_VIEW	 0xC0000019
+#define STATUS_UNABLE_TO_FREE_VM	 0xC000001A
+#define STATUS_UNABLE_TO_DELETE_SECTION	 0xC000001B
+#define STATUS_INVALID_SYSTEM_SERVICE	 0xC000001C
+#define STATUS_ILLEGAL_INSTRUCTION	 0xC000001D
+#define STATUS_INVALID_LOCK_SEQUENCE	 0xC000001E
+#define STATUS_INVALID_VIEW_SIZE	 0xC000001F
+#define STATUS_INVALID_FILE_FOR_SECTION	 0xC0000020
+#define STATUS_ALREADY_COMMITTED	 0xC0000021
+#define STATUS_ACCESS_DENIED	 0xC0000022
+#define STATUS_BUFFER_TOO_SMALL	 0xC0000023
+#define STATUS_OBJECT_TYPE_MISMATCH	 0xC0000024
+#define STATUS_NONCONTINUABLE_EXCEPTION	 0xC0000025
+#define STATUS_INVALID_DISPOSITION	 0xC0000026
+#define STATUS_UNWIND	 0xC0000027
+#define STATUS_BAD_STACK	 0xC0000028
+#define STATUS_INVALID_UNWIND_TARGET	 0xC0000029
+#define STATUS_NOT_LOCKED	 0xC000002A
+#define STATUS_PARITY_ERROR	 0xC000002B
+#define STATUS_UNABLE_TO_DECOMMIT_VM	 0xC000002C
+#define STATUS_NOT_COMMITTED	 0xC000002D
+#define STATUS_INVALID_PORT_ATTRIBUTES	 0xC000002E
+#define STATUS_PORT_MESSAGE_TOO_LONG	 0xC000002F
+#define STATUS_INVALID_PARAMETER_MIX	 0xC0000030
+#define STATUS_INVALID_QUOTA_LOWER	 0xC0000031
+#define STATUS_DISK_CORRUPT_ERROR	 0xC0000032
+#define STATUS_OBJECT_NAME_INVALID	 0xC0000033
+#define STATUS_OBJECT_NAME_NOT_FOUND	 0xC0000034
+#define STATUS_OBJECT_NAME_COLLISION	 0xC0000035
+#define STATUS_PORT_DISCONNECTED	 0xC0000037
+#define STATUS_DEVICE_ALREADY_ATTACHED	 0xC0000038
+#define STATUS_OBJECT_PATH_INVALID	 0xC0000039
+#define STATUS_OBJECT_PATH_NOT_FOUND	 0xC000003A
+#define STATUS_OBJECT_PATH_SYNTAX_BAD	 0xC000003B
+#define STATUS_DATA_OVERRUN	 0xC000003C
+#define STATUS_DATA_LATE_ERROR	 0xC000003D
+#define STATUS_DATA_ERROR	 0xC000003E
+#define STATUS_CRC_ERROR	 0xC000003F
+#define STATUS_SECTION_TOO_BIG	 0xC0000040
+#define STATUS_PORT_CONNECTION_REFUSED	 0xC0000041
+#define STATUS_INVALID_PORT_HANDLE	 0xC0000042
+#define STATUS_SHARING_VIOLATION	 0xC0000043
+#define STATUS_QUOTA_EXCEEDED	 0xC0000044
+#define STATUS_INVALID_PAGE_PROTECTION	 0xC0000045
+#define STATUS_MUTANT_NOT_OWNED	 0xC0000046
+#define STATUS_SEMAPHORE_LIMIT_EXCEEDED	 0xC0000047
+#define STATUS_PORT_ALREADY_SET	 0xC0000048
+#define STATUS_SECTION_NOT_IMAGE	 0xC0000049
+#define STATUS_SUSPEND_COUNT_EXCEEDED	 0xC000004A
+#define STATUS_THREAD_IS_TERMINATING	 0xC000004B
+#define STATUS_BAD_WORKING_SET_LIMIT	 0xC000004C
+#define STATUS_INCOMPATIBLE_FILE_MAP	 0xC000004D
+#define STATUS_SECTION_PROTECTION	 0xC000004E
+#define STATUS_EAS_NOT_SUPPORTED	 0xC000004F
+#define STATUS_EA_TOO_LARGE	 0xC0000050
+#define STATUS_NONEXISTENT_EA_ENTRY	 0xC0000051
+#define STATUS_NO_EAS_ON_FILE	 0xC0000052
+#define STATUS_EA_CORRUPT_ERROR	 0xC0000053
+#define STATUS_FILE_LOCK_CONFLICT	 0xC0000054
+#define STATUS_LOCK_NOT_GRANTED	 0xC0000055
+#define STATUS_DELETE_PENDING	 0xC0000056
+#define STATUS_CTL_FILE_NOT_SUPPORTED	 0xC0000057
+#define STATUS_UNKNOWN_REVISION	 0xC0000058
+#define STATUS_REVISION_MISMATCH	 0xC0000059
+#define STATUS_INVALID_OWNER	 0xC000005A
+#define STATUS_INVALID_PRIMARY_GROUP	 0xC000005B
+#define STATUS_NO_IMPERSONATION_TOKEN	 0xC000005C
+#define STATUS_CANT_DISABLE_MANDATORY	 0xC000005D
+#define STATUS_NO_LOGON_SERVERS	 0xC000005E
+#define STATUS_NO_SUCH_LOGON_SESSION	 0xC000005F
+#define STATUS_NO_SUCH_PRIVILEGE	 0xC0000060
+#define STATUS_PRIVILEGE_NOT_HELD	 0xC0000061
+#define STATUS_INVALID_ACCOUNT_NAME	 0xC0000062
+#define STATUS_USER_EXISTS	 0xC0000063
+#define STATUS_NO_SUCH_USER	 0xC0000064
+#define STATUS_GROUP_EXISTS	 0xC0000065
+#define STATUS_NO_SUCH_GROUP	 0xC0000066
+#define STATUS_MEMBER_IN_GROUP	 0xC0000067
+#define STATUS_MEMBER_NOT_IN_GROUP	 0xC0000068
+#define STATUS_LAST_ADMIN	 0xC0000069
+#define STATUS_WRONG_PASSWORD	 0xC000006A
+#define STATUS_ILL_FORMED_PASSWORD	 0xC000006B
+#define STATUS_PASSWORD_RESTRICTION	 0xC000006C
+#define STATUS_LOGON_FAILURE	 0xC000006D
+#define STATUS_ACCOUNT_RESTRICTION	 0xC000006E
+#define STATUS_INVALID_LOGON_HOURS	 0xC000006F
+#define STATUS_INVALID_WORKSTATION	 0xC0000070
+#define STATUS_PASSWORD_EXPIRED	 0xC0000071
+#define STATUS_ACCOUNT_DISABLED	 0xC0000072
+#define STATUS_NONE_MAPPED	 0xC0000073
+#define STATUS_TOO_MANY_LUIDS_REQUESTED	 0xC0000074
+#define STATUS_LUIDS_EXHAUSTED	 0xC0000075
+#define STATUS_INVALID_SUB_AUTHORITY	 0xC0000076
+#define STATUS_INVALID_ACL	 0xC0000077
+#define STATUS_INVALID_SID	 0xC0000078
+#define STATUS_INVALID_SECURITY_DESCR	 0xC0000079
+#define STATUS_PROCEDURE_NOT_FOUND	 0xC000007A
+#define STATUS_INVALID_IMAGE_FORMAT	 0xC000007B
+#define STATUS_NO_TOKEN	 0xC000007C
+#define STATUS_BAD_INHERITANCE_ACL	 0xC000007D
+#define STATUS_RANGE_NOT_LOCKED	 0xC000007E
+#define STATUS_DISK_FULL	 0xC000007F
+#define STATUS_SERVER_DISABLED	 0xC0000080
+#define STATUS_SERVER_NOT_DISABLED	 0xC0000081
+#define STATUS_TOO_MANY_GUIDS_REQUESTED	 0xC0000082
+#define STATUS_GUIDS_EXHAUSTED	 0xC0000083
+#define STATUS_INVALID_ID_AUTHORITY	 0xC0000084
+#define STATUS_AGENTS_EXHAUSTED	 0xC0000085
+#define STATUS_INVALID_VOLUME_LABEL	 0xC0000086
+#define STATUS_SECTION_NOT_EXTENDED	 0xC0000087
+#define STATUS_NOT_MAPPED_DATA	 0xC0000088
+#define STATUS_RESOURCE_DATA_NOT_FOUND	 0xC0000089
+#define STATUS_RESOURCE_TYPE_NOT_FOUND	 0xC000008A
+#define STATUS_RESOURCE_NAME_NOT_FOUND	 0xC000008B
+#define STATUS_ARRAY_BOUNDS_EXCEEDED	 0xC000008C
+#define STATUS_FLOAT_DENORMAL_OPERAND	 0xC000008D
+#define STATUS_FLOAT_DIVIDE_BY_ZERO	 0xC000008E
+#define STATUS_FLOAT_INEXACT_RESULT	 0xC000008F
+#define STATUS_FLOAT_INVALID_OPERATION	 0xC0000090
+#define STATUS_FLOAT_OVERFLOW	 0xC0000091
+#define STATUS_FLOAT_STACK_CHECK	 0xC0000092
+#define STATUS_FLOAT_UNDERFLOW	 0xC0000093
+#define STATUS_INTEGER_DIVIDE_BY_ZERO	 0xC0000094
+#define STATUS_INTEGER_OVERFLOW	 0xC0000095
+#define STATUS_PRIVILEGED_INSTRUCTION	 0xC0000096
+#define STATUS_TOO_MANY_PAGING_FILES	 0xC0000097
+#define STATUS_FILE_INVALID	 0xC0000098
+#define STATUS_ALLOTTED_SPACE_EXCEEDED	 0xC0000099
+#define STATUS_INSUFFICIENT_RESOURCES	 0xC000009A
+#define STATUS_DFS_EXIT_PATH_FOUND	 0xC000009B
+#define STATUS_DEVICE_DATA_ERROR	 0xC000009C
+#define STATUS_DEVICE_NOT_CONNECTED	 0xC000009D
+#define STATUS_DEVICE_POWER_FAILURE	 0xC000009E
+#define STATUS_FREE_VM_NOT_AT_BASE	 0xC000009F
+#define STATUS_MEMORY_NOT_ALLOCATED	 0xC00000A0
+#define STATUS_WORKING_SET_QUOTA	 0xC00000A1
+#define STATUS_MEDIA_WRITE_PROTECTED	 0xC00000A2
+#define STATUS_DEVICE_NOT_READY	 0xC00000A3
+#define STATUS_INVALID_GROUP_ATTRIBUTES	 0xC00000A4
+#define STATUS_BAD_IMPERSONATION_LEVEL	 0xC00000A5
+#define STATUS_CANT_OPEN_ANONYMOUS	 0xC00000A6
+#define STATUS_BAD_VALIDATION_CLASS	 0xC00000A7
+#define STATUS_BAD_TOKEN_TYPE	 0xC00000A8
+#define STATUS_BAD_MASTER_BOOT_RECORD	 0xC00000A9
+#define STATUS_INSTRUCTION_MISALIGNMENT	 0xC00000AA
+#define STATUS_INSTANCE_NOT_AVAILABLE	 0xC00000AB
+#define STATUS_PIPE_NOT_AVAILABLE	 0xC00000AC
+#define STATUS_INVALID_PIPE_STATE	 0xC00000AD
+#define STATUS_PIPE_BUSY	 0xC00000AE
+#define STATUS_ILLEGAL_FUNCTION	 0xC00000AF
+#define STATUS_PIPE_DISCONNECTED	 0xC00000B0
+#define STATUS_PIPE_CLOSING	 0xC00000B1
+#define STATUS_PIPE_CONNECTED	 0xC00000B2
+#define STATUS_PIPE_LISTENING	 0xC00000B3
+#define STATUS_INVALID_READ_MODE	 0xC00000B4
+#define STATUS_IO_TIMEOUT	 0xC00000B5
+#define STATUS_FILE_FORCED_CLOSED	 0xC00000B6
+#define STATUS_PROFILING_NOT_STARTED	 0xC00000B7
+#define STATUS_PROFILING_NOT_STOPPED	 0xC00000B8
+#define STATUS_COULD_NOT_INTERPRET	 0xC00000B9
+#define STATUS_FILE_IS_A_DIRECTORY	 0xC00000BA
+#define STATUS_NOT_SUPPORTED	 0xC00000BB
+#define STATUS_REMOTE_NOT_LISTENING	 0xC00000BC
+#define STATUS_DUPLICATE_NAME	 0xC00000BD
+#define STATUS_BAD_NETWORK_PATH	 0xC00000BE
+#define STATUS_NETWORK_BUSY	 0xC00000BF
+#define STATUS_DEVICE_DOES_NOT_EXIST	 0xC00000C0
+#define STATUS_TOO_MANY_COMMANDS	 0xC00000C1
+#define STATUS_ADAPTER_HARDWARE_ERROR	 0xC00000C2
+#define STATUS_INVALID_NETWORK_RESPONSE	 0xC00000C3
+#define STATUS_UNEXPECTED_NETWORK_ERROR	 0xC00000C4
+#define STATUS_BAD_REMOTE_ADAPTER	 0xC00000C5
+#define STATUS_PRINT_QUEUE_FULL	 0xC00000C6
+#define STATUS_NO_SPOOL_SPACE	 0xC00000C7
+#define STATUS_PRINT_CANCELLED	 0xC00000C8
+#define STATUS_NETWORK_NAME_DELETED	 0xC00000C9
+#define STATUS_NETWORK_ACCESS_DENIED	 0xC00000CA
+#define STATUS_BAD_DEVICE_TYPE	 0xC00000CB
+#define STATUS_BAD_NETWORK_NAME	 0xC00000CC
+#define STATUS_TOO_MANY_NAMES	 0xC00000CD
+#define STATUS_TOO_MANY_SESSIONS	 0xC00000CE
+#define STATUS_SHARING_PAUSED	 0xC00000CF
+#define STATUS_REQUEST_NOT_ACCEPTED	 0xC00000D0
+#define STATUS_REDIRECTOR_PAUSED	 0xC00000D1
+#define STATUS_NET_WRITE_FAULT	 0xC00000D2
+#define STATUS_PROFILING_AT_LIMIT	 0xC00000D3
+#define STATUS_NOT_SAME_DEVICE	 0xC00000D4
+#define STATUS_FILE_RENAMED	 0xC00000D5
+#define STATUS_VIRTUAL_CIRCUIT_CLOSED	 0xC00000D6
+#define STATUS_NO_SECURITY_ON_OBJECT	 0xC00000D7
+#define STATUS_CANT_WAIT	 0xC00000D8
+#define STATUS_PIPE_EMPTY	 0xC00000D9
+#define STATUS_CANT_ACCESS_DOMAIN_INFO	 0xC00000DA
+#define STATUS_CANT_TERMINATE_SELF	 0xC00000DB
+#define STATUS_INVALID_SERVER_STATE	 0xC00000DC
+#define STATUS_INVALID_DOMAIN_STATE	 0xC00000DD
+#define STATUS_INVALID_DOMAIN_ROLE	 0xC00000DE
+#define STATUS_NO_SUCH_DOMAIN	 0xC00000DF
+#define STATUS_DOMAIN_EXISTS	 0xC00000E0
+#define STATUS_DOMAIN_LIMIT_EXCEEDED	 0xC00000E1
+#define STATUS_OPLOCK_NOT_GRANTED	 0xC00000E2
+#define STATUS_INVALID_OPLOCK_PROTOCOL	 0xC00000E3
+#define STATUS_INTERNAL_DB_CORRUPTION	 0xC00000E4
+#define STATUS_INTERNAL_ERROR	 0xC00000E5
+#define STATUS_GENERIC_NOT_MAPPED	 0xC00000E6
+#define STATUS_BAD_DESCRIPTOR_FORMAT	 0xC00000E7
+#define STATUS_INVALID_USER_BUFFER	 0xC00000E8
+#define STATUS_UNEXPECTED_IO_ERROR	 0xC00000E9
+#define STATUS_UNEXPECTED_MM_CREATE_ERR	 0xC00000EA
+#define STATUS_UNEXPECTED_MM_MAP_ERROR	 0xC00000EB
+#define STATUS_UNEXPECTED_MM_EXTEND_ERR	 0xC00000EC
+#define STATUS_NOT_LOGON_PROCESS	 0xC00000ED
+#define STATUS_LOGON_SESSION_EXISTS	 0xC00000EE
+#define STATUS_INVALID_PARAMETER_1	 0xC00000EF
+#define STATUS_INVALID_PARAMETER_2	 0xC00000F0
+#define STATUS_INVALID_PARAMETER_3	 0xC00000F1
+#define STATUS_INVALID_PARAMETER_4	 0xC00000F2
+#define STATUS_INVALID_PARAMETER_5	 0xC00000F3
+#define STATUS_INVALID_PARAMETER_6	 0xC00000F4
+#define STATUS_INVALID_PARAMETER_7	 0xC00000F5
+#define STATUS_INVALID_PARAMETER_8	 0xC00000F6
+#define STATUS_INVALID_PARAMETER_9	 0xC00000F7
+#define STATUS_INVALID_PARAMETER_10	 0xC00000F8
+#define STATUS_INVALID_PARAMETER_11	 0xC00000F9
+#define STATUS_INVALID_PARAMETER_12	 0xC00000FA
+#define STATUS_REDIRECTOR_NOT_STARTED	 0xC00000FB
+#define STATUS_REDIRECTOR_STARTED	 0xC00000FC
+#define STATUS_STACK_OVERFLOW	 0xC00000FD
+#define STATUS_NO_SUCH_PACKAGE	 0xC00000FE
+#define STATUS_BAD_FUNCTION_TABLE	 0xC00000FF
+#define STATUS_VARIABLE_NOT_FOUND	 0xC0000100
+#define STATUS_DIRECTORY_NOT_EMPTY	 0xC0000101
+#define STATUS_FILE_CORRUPT_ERROR	 0xC0000102
+#define STATUS_NOT_A_DIRECTORY	 0xC0000103
+#define STATUS_BAD_LOGON_SESSION_STATE	 0xC0000104
+#define STATUS_LOGON_SESSION_COLLISION	 0xC0000105
+#define STATUS_NAME_TOO_LONG	 0xC0000106
+#define STATUS_FILES_OPEN	 0xC0000107
+#define STATUS_CONNECTION_IN_USE	 0xC0000108
+#define STATUS_MESSAGE_NOT_FOUND	 0xC0000109
+#define STATUS_PROCESS_IS_TERMINATING	 0xC000010A
+#define STATUS_INVALID_LOGON_TYPE	 0xC000010B
+#define STATUS_NO_GUID_TRANSLATION	 0xC000010C
+#define STATUS_CANNOT_IMPERSONATE	 0xC000010D
+#define STATUS_IMAGE_ALREADY_LOADED	 0xC000010E
+#define STATUS_ABIOS_NOT_PRESENT	 0xC000010F
+#define STATUS_ABIOS_LID_NOT_EXIST	 0xC0000110
+#define STATUS_ABIOS_LID_ALREADY_OWNED	 0xC0000111
+#define STATUS_ABIOS_NOT_LID_OWNER	 0xC0000112
+#define STATUS_ABIOS_INVALID_COMMAND	 0xC0000113
+#define STATUS_ABIOS_INVALID_LID	 0xC0000114
+#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE	 0xC0000115
+#define STATUS_ABIOS_INVALID_SELECTOR	 0xC0000116
+#define STATUS_NO_LDT	 0xC0000117
+#define STATUS_INVALID_LDT_SIZE	 0xC0000118
+#define STATUS_INVALID_LDT_OFFSET	 0xC0000119
+#define STATUS_INVALID_LDT_DESCRIPTOR	 0xC000011A
+#define STATUS_INVALID_IMAGE_NE_FORMAT	 0xC000011B
+#define STATUS_RXACT_INVALID_STATE	 0xC000011C
+#define STATUS_RXACT_COMMIT_FAILURE	 0xC000011D
+#define STATUS_MAPPED_FILE_SIZE_ZERO	 0xC000011E
+#define STATUS_TOO_MANY_OPENED_FILES	 0xC000011F
+#define STATUS_CANCELLED	 0xC0000120
+#define STATUS_CANNOT_DELETE	 0xC0000121
+#define STATUS_INVALID_COMPUTER_NAME	 0xC0000122
+#define STATUS_FILE_DELETED	 0xC0000123
+#define STATUS_SPECIAL_ACCOUNT	 0xC0000124
+#define STATUS_SPECIAL_GROUP	 0xC0000125
+#define STATUS_SPECIAL_USER	 0xC0000126
+#define STATUS_MEMBERS_PRIMARY_GROUP	 0xC0000127
+#define STATUS_FILE_CLOSED	 0xC0000128
+#define STATUS_TOO_MANY_THREADS	 0xC0000129
+#define STATUS_THREAD_NOT_IN_PROCESS	 0xC000012A
+#define STATUS_TOKEN_ALREADY_IN_USE	 0xC000012B
+#define STATUS_PAGEFILE_QUOTA_EXCEEDED	 0xC000012C
+#define STATUS_COMMITMENT_LIMIT	 0xC000012D
+#define STATUS_INVALID_IMAGE_LE_FORMAT	 0xC000012E
+#define STATUS_INVALID_IMAGE_NOT_MZ	 0xC000012F
+#define STATUS_INVALID_IMAGE_PROTECT	 0xC0000130
+#define STATUS_INVALID_IMAGE_WIN_16	 0xC0000131
+#define STATUS_LOGON_SERVER_CONFLICT	 0xC0000132
+#define STATUS_TIME_DIFFERENCE_AT_DC	 0xC0000133
+#define STATUS_SYNCHRONIZATION_REQUIRED	 0xC0000134
+#define STATUS_DLL_NOT_FOUND	 0xC0000135
+#define STATUS_OPEN_FAILED	 0xC0000136
+#define STATUS_IO_PRIVILEGE_FAILED	 0xC0000137
+#define STATUS_ORDINAL_NOT_FOUND	 0xC0000138
+#define STATUS_ENTRYPOINT_NOT_FOUND	 0xC0000139
+#define STATUS_CONTROL_C_EXIT	 0xC000013A
+#define STATUS_LOCAL_DISCONNECT	 0xC000013B
+#define STATUS_REMOTE_DISCONNECT	 0xC000013C
+#define STATUS_REMOTE_RESOURCES	 0xC000013D
+#define STATUS_LINK_FAILED	 0xC000013E
+#define STATUS_LINK_TIMEOUT	 0xC000013F
+#define STATUS_INVALID_CONNECTION	 0xC0000140
+#define STATUS_INVALID_ADDRESS	 0xC0000141
+#define STATUS_DLL_INIT_FAILED	 0xC0000142
+#define STATUS_MISSING_SYSTEMFILE	 0xC0000143
+#define STATUS_UNHANDLED_EXCEPTION	 0xC0000144
+#define STATUS_APP_INIT_FAILURE	 0xC0000145
+#define STATUS_PAGEFILE_CREATE_FAILED	 0xC0000146
+#define STATUS_NO_PAGEFILE	 0xC0000147
+#define STATUS_INVALID_LEVEL	 0xC0000148
+#define STATUS_WRONG_PASSWORD_CORE	 0xC0000149
+#define STATUS_ILLEGAL_FLOAT_CONTEXT	 0xC000014A
+#define STATUS_PIPE_BROKEN	 0xC000014B
+#define STATUS_REGISTRY_CORRUPT	 0xC000014C
+#define STATUS_REGISTRY_IO_FAILED	 0xC000014D
+#define STATUS_NO_EVENT_PAIR	 0xC000014E
+#define STATUS_UNRECOGNIZED_VOLUME	 0xC000014F
+#define STATUS_SERIAL_NO_DEVICE_INITED	 0xC0000150
+#define STATUS_NO_SUCH_ALIAS	 0xC0000151
+#define STATUS_MEMBER_NOT_IN_ALIAS	 0xC0000152
+#define STATUS_MEMBER_IN_ALIAS	 0xC0000153
+#define STATUS_ALIAS_EXISTS	 0xC0000154
+#define STATUS_LOGON_NOT_GRANTED	 0xC0000155
+#define STATUS_TOO_MANY_SECRETS	 0xC0000156
+#define STATUS_SECRET_TOO_LONG	 0xC0000157
+#define STATUS_INTERNAL_DB_ERROR	 0xC0000158
+#define STATUS_FULLSCREEN_MODE	 0xC0000159
+#define STATUS_TOO_MANY_CONTEXT_IDS	 0xC000015A
+#define STATUS_LOGON_TYPE_NOT_GRANTED	 0xC000015B
+#define STATUS_NOT_REGISTRY_FILE	 0xC000015C
+#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED	 0xC000015D
+#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR	 0xC000015E
+#define STATUS_FT_MISSING_MEMBER	 0xC000015F
+#define STATUS_ILL_FORMED_SERVICE_ENTRY	 0xC0000160
+#define STATUS_ILLEGAL_CHARACTER	 0xC0000161
+#define STATUS_UNMAPPABLE_CHARACTER	 0xC0000162
+#define STATUS_UNDEFINED_CHARACTER	 0xC0000163
+#define STATUS_FLOPPY_VOLUME	 0xC0000164
+#define STATUS_FLOPPY_ID_MARK_NOT_FOUND	 0xC0000165
+#define STATUS_FLOPPY_WRONG_CYLINDER	 0xC0000166
+#define STATUS_FLOPPY_UNKNOWN_ERROR	 0xC0000167
+#define STATUS_FLOPPY_BAD_REGISTERS	 0xC0000168
+#define STATUS_DISK_RECALIBRATE_FAILED	 0xC0000169
+#define STATUS_DISK_OPERATION_FAILED	 0xC000016A
+#define STATUS_DISK_RESET_FAILED	 0xC000016B
+#define STATUS_SHARED_IRQ_BUSY	 0xC000016C
+#define STATUS_FT_ORPHANING	 0xC000016D
+#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT	 0xC000016E
+#define STATUS_PARTITION_FAILURE	 0xC0000172
+#define STATUS_INVALID_BLOCK_LENGTH	 0xC0000173
+#define STATUS_DEVICE_NOT_PARTITIONED	 0xC0000174
+#define STATUS_UNABLE_TO_LOCK_MEDIA	 0xC0000175
+#define STATUS_UNABLE_TO_UNLOAD_MEDIA	 0xC0000176
+#define STATUS_EOM_OVERFLOW	 0xC0000177
+#define STATUS_NO_MEDIA	 0xC0000178
+#define STATUS_NO_SUCH_MEMBER	 0xC000017A
+#define STATUS_INVALID_MEMBER	 0xC000017B
+#define STATUS_KEY_DELETED	 0xC000017C
+#define STATUS_NO_LOG_SPACE	 0xC000017D
+#define STATUS_TOO_MANY_SIDS	 0xC000017E
+#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED	 0xC000017F
+#define STATUS_KEY_HAS_CHILDREN	 0xC0000180
+#define STATUS_CHILD_MUST_BE_VOLATILE	 0xC0000181
+#define STATUS_DEVICE_CONFIGURATION_ERROR	 0xC0000182
+#define STATUS_DRIVER_INTERNAL_ERROR	 0xC0000183
+#define STATUS_INVALID_DEVICE_STATE	 0xC0000184
+#define STATUS_IO_DEVICE_ERROR	 0xC0000185
+#define STATUS_DEVICE_PROTOCOL_ERROR	 0xC0000186
+#define STATUS_BACKUP_CONTROLLER	 0xC0000187
+#define STATUS_LOG_FILE_FULL	 0xC0000188
+#define STATUS_TOO_LATE	 0xC0000189
+#define STATUS_NO_TRUST_LSA_SECRET	 0xC000018A
+#define STATUS_NO_TRUST_SAM_ACCOUNT	 0xC000018B
+#define STATUS_TRUSTED_DOMAIN_FAILURE	 0xC000018C
+#define STATUS_TRUSTED_RELATIONSHIP_FAILURE	 0xC000018D
+#define STATUS_EVENTLOG_FILE_CORRUPT	 0xC000018E
+#define STATUS_EVENTLOG_CANT_START	 0xC000018F
+#define STATUS_TRUST_FAILURE	 0xC0000190
+#define STATUS_MUTANT_LIMIT_EXCEEDED	 0xC0000191
+#define STATUS_NETLOGON_NOT_STARTED	 0xC0000192
+#define STATUS_ACCOUNT_EXPIRED	 0xC0000193
+#define STATUS_POSSIBLE_DEADLOCK	 0xC0000194
+#define STATUS_NETWORK_CREDENTIAL_CONFLICT	 0xC0000195
+#define STATUS_REMOTE_SESSION_LIMIT	 0xC0000196
+#define STATUS_EVENTLOG_FILE_CHANGED	 0xC0000197
+#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT	 0xC0000198
+#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT	 0xC0000199
+#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT	 0xC000019A
+#define STATUS_DOMAIN_TRUST_INCONSISTENT	 0xC000019B
+#define STATUS_FS_DRIVER_REQUIRED	 0xC000019C
+#define STATUS_IMAGE_ALREADY_LOADED_AS_DLL	 0xC000019D
+#define STATUS_NETWORK_OPEN_RESTRICTION	 0xC0000201
+#define STATUS_NO_USER_SESSION_KEY	 0xC0000202
+#define STATUS_USER_SESSION_DELETED	 0xC0000203
+#define STATUS_RESOURCE_LANG_NOT_FOUND	 0xC0000204
+#define STATUS_INSUFF_SERVER_RESOURCES	 0xC0000205
+#define STATUS_INVALID_BUFFER_SIZE	 0xC0000206
+#define STATUS_INVALID_ADDRESS_COMPONENT	 0xC0000207
+#define STATUS_INVALID_ADDRESS_WILDCARD	 0xC0000208
+#define STATUS_TOO_MANY_ADDRESSES	 0xC0000209
+#define STATUS_ADDRESS_ALREADY_EXISTS	 0xC000020A
+#define STATUS_ADDRESS_CLOSED	 0xC000020B
+#define STATUS_CONNECTION_DISCONNECTED	 0xC000020C
+#define STATUS_CONNECTION_RESET	 0xC000020D
+#define STATUS_TOO_MANY_NODES	 0xC000020E
+#define STATUS_TRANSACTION_ABORTED	 0xC000020F
+#define STATUS_TRANSACTION_TIMED_OUT	 0xC0000210
+#define STATUS_TRANSACTION_NO_RELEASE	 0xC0000211
+#define STATUS_TRANSACTION_NO_MATCH	 0xC0000212
+#define STATUS_TRANSACTION_RESPONDED	 0xC0000213
+#define STATUS_TRANSACTION_INVALID_ID	 0xC0000214
+#define STATUS_TRANSACTION_INVALID_TYPE	 0xC0000215
+#define STATUS_NOT_SERVER_SESSION	 0xC0000216
+#define STATUS_NOT_CLIENT_SESSION	 0xC0000217
+#define STATUS_CANNOT_LOAD_REGISTRY_FILE	 0xC0000218
+#define STATUS_DEBUG_ATTACH_FAILED	 0xC0000219
+#define STATUS_SYSTEM_PROCESS_TERMINATED	 0xC000021A
+#define STATUS_DATA_NOT_ACCEPTED	 0xC000021B
+#define STATUS_NO_BROWSER_SERVERS_FOUND	 0xC000021C
+#define STATUS_VDM_HARD_ERROR	 0xC000021D
+#define STATUS_DRIVER_CANCEL_TIMEOUT	 0xC000021E
+#define STATUS_REPLY_MESSAGE_MISMATCH	 0xC000021F
+#define STATUS_MAPPED_ALIGNMENT	 0xC0000220
+#define STATUS_IMAGE_CHECKSUM_MISMATCH	 0xC0000221
+#define STATUS_LOST_WRITEBEHIND_DATA	 0xC0000222
+#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID	 0xC0000223
+#define STATUS_PASSWORD_MUST_CHANGE	 0xC0000224
+#define STATUS_NOT_FOUND	 0xC0000225
+#define STATUS_NOT_TINY_STREAM	 0xC0000226
+#define STATUS_RECOVERY_FAILURE	 0xC0000227
+#define STATUS_STACK_OVERFLOW_READ	 0xC0000228
+#define STATUS_FAIL_CHECK	 0xC0000229
+#define STATUS_DUPLICATE_OBJECTID	 0xC000022A
+#define STATUS_OBJECTID_EXISTS	 0xC000022B
+#define STATUS_CONVERT_TO_LARGE	 0xC000022C
+#define STATUS_RETRY	 0xC000022D
+#define STATUS_FOUND_OUT_OF_SCOPE	 0xC000022E
+#define STATUS_ALLOCATE_BUCKET	 0xC000022F
+#define STATUS_PROPSET_NOT_FOUND	 0xC0000230
+#define STATUS_MARSHALL_OVERFLOW	 0xC0000231
+#define STATUS_INVALID_VARIANT	 0xC0000232
+#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND	 0xC0000233
+#define STATUS_ACCOUNT_LOCKED_OUT	 0xC0000234
+#define STATUS_HANDLE_NOT_CLOSABLE	 0xC0000235
+#define STATUS_CONNECTION_REFUSED	 0xC0000236
+#define STATUS_GRACEFUL_DISCONNECT	 0xC0000237
+#define STATUS_ADDRESS_ALREADY_ASSOCIATED	 0xC0000238
+#define STATUS_ADDRESS_NOT_ASSOCIATED	 0xC0000239
+#define STATUS_CONNECTION_INVALID	 0xC000023A
+#define STATUS_CONNECTION_ACTIVE	 0xC000023B
+#define STATUS_NETWORK_UNREACHABLE	 0xC000023C
+#define STATUS_HOST_UNREACHABLE	 0xC000023D
+#define STATUS_PROTOCOL_UNREACHABLE	 0xC000023E
+#define STATUS_PORT_UNREACHABLE	 0xC000023F
+#define STATUS_REQUEST_ABORTED	 0xC0000240
+#define STATUS_CONNECTION_ABORTED	 0xC0000241
+#define STATUS_BAD_COMPRESSION_BUFFER	 0xC0000242
+#define STATUS_USER_MAPPED_FILE	 0xC0000243
+#define STATUS_AUDIT_FAILED	 0xC0000244
+#define STATUS_TIMER_RESOLUTION_NOT_SET	 0xC0000245
+#define STATUS_CONNECTION_COUNT_LIMIT	 0xC0000246
+#define STATUS_LOGIN_TIME_RESTRICTION	 0xC0000247
+#define STATUS_LOGIN_WKSTA_RESTRICTION	 0xC0000248
+#define STATUS_IMAGE_MP_UP_MISMATCH	 0xC0000249
+#define STATUS_INSUFFICIENT_LOGON_INFO	 0xC0000250
+#define STATUS_BAD_DLL_ENTRYPOINT	 0xC0000251
+#define STATUS_BAD_SERVICE_ENTRYPOINT	 0xC0000252
+#define STATUS_LPC_REPLY_LOST	 0xC0000253
+#define STATUS_IP_ADDRESS_CONFLICT1	 0xC0000254
+#define STATUS_IP_ADDRESS_CONFLICT2	 0xC0000255
+#define STATUS_REGISTRY_QUOTA_LIMIT	 0xC0000256
+#define STATUS_PATH_NOT_COVERED	 0xC0000257
+#define STATUS_NO_CALLBACK_ACTIVE	 0xC0000258
+#define STATUS_LICENSE_QUOTA_EXCEEDED	 0xC0000259
+#define STATUS_PWD_TOO_SHORT	 0xC000025A
+#define STATUS_PWD_TOO_RECENT	 0xC000025B
+#define STATUS_PWD_HISTORY_CONFLICT	 0xC000025C
+#define STATUS_PLUGPLAY_NO_DEVICE	 0xC000025E
+#define STATUS_UNSUPPORTED_COMPRESSION	 0xC000025F
+#define STATUS_INVALID_HW_PROFILE	 0xC0000260
+#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH	 0xC0000261
+#define STATUS_DRIVER_ORDINAL_NOT_FOUND	 0xC0000262
+#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND	 0xC0000263
+#define STATUS_RESOURCE_NOT_OWNED	 0xC0000264
+#define STATUS_TOO_MANY_LINKS	 0xC0000265
+#define STATUS_QUOTA_LIST_INCONSISTENT	 0xC0000266
+#define STATUS_FILE_IS_OFFLINE	 0xC0000267
+#define STATUS_EVALUATION_EXPIRATION	 0xC0000268
+#define STATUS_ILLEGAL_DLL_RELOCATION	 0xC0000269
+#define STATUS_LICENSE_VIOLATION	 0xC000026A
+#define STATUS_DLL_INIT_FAILED_LOGOFF	 0xC000026B
+#define STATUS_DRIVER_UNABLE_TO_LOAD	 0xC000026C
+#define STATUS_DFS_UNAVAILABLE	 0xC000026D
+#define STATUS_VOLUME_DISMOUNTED	 0xC000026E
+#define STATUS_WX86_INTERNAL_ERROR	 0xC000026F
+#define STATUS_WX86_FLOAT_STACK_CHECK	 0xC0000270
+#define STATUS_VALIDATE_CONTINUE	 0xC0000271
+#define STATUS_NO_MATCH	 0xC0000272
+#define STATUS_NO_MORE_MATCHES	 0xC0000273
+#define STATUS_NOT_A_REPARSE_POINT	 0xC0000275
+#define STATUS_IO_REPARSE_TAG_INVALID	 0xC0000276
+#define STATUS_IO_REPARSE_TAG_MISMATCH	 0xC0000277
+#define STATUS_IO_REPARSE_DATA_INVALID	 0xC0000278
+#define STATUS_IO_REPARSE_TAG_NOT_HANDLED	 0xC0000279
+#define STATUS_REPARSE_POINT_NOT_RESOLVED	 0xC0000280
+#define STATUS_DIRECTORY_IS_A_REPARSE_POINT	 0xC0000281
+#define STATUS_RANGE_LIST_CONFLICT	 0xC0000282
+#define STATUS_SOURCE_ELEMENT_EMPTY	 0xC0000283
+#define STATUS_DESTINATION_ELEMENT_FULL	 0xC0000284
+#define STATUS_ILLEGAL_ELEMENT_ADDRESS	 0xC0000285
+#define STATUS_MAGAZINE_NOT_PRESENT	 0xC0000286
+#define STATUS_REINITIALIZATION_NEEDED	 0xC0000287
+#define STATUS_ENCRYPTION_FAILED	 0xC000028A
+#define STATUS_DECRYPTION_FAILED	 0xC000028B
+#define STATUS_RANGE_NOT_FOUND	 0xC000028C
+#define STATUS_NO_RECOVERY_POLICY	 0xC000028D
+#define STATUS_NO_EFS	 0xC000028E
+#define STATUS_WRONG_EFS	 0xC000028F
+#define STATUS_NO_USER_KEYS	 0xC0000290
+#define STATUS_FILE_NOT_ENCRYPTED	 0xC0000291
+#define STATUS_NOT_EXPORT_FORMAT	 0xC0000292
+#define STATUS_FILE_ENCRYPTED	 0xC0000293
+#define STATUS_WMI_GUID_NOT_FOUND	 0xC0000295
+#define STATUS_WMI_INSTANCE_NOT_FOUND	 0xC0000296
+#define STATUS_WMI_ITEMID_NOT_FOUND	 0xC0000297
+#define STATUS_WMI_TRY_AGAIN	 0xC0000298
+#define STATUS_SHARED_POLICY	 0xC0000299
+#define STATUS_POLICY_OBJECT_NOT_FOUND	 0xC000029A
+#define STATUS_POLICY_ONLY_IN_DS	 0xC000029B
+#define STATUS_VOLUME_NOT_UPGRADED	 0xC000029C
+#define STATUS_REMOTE_STORAGE_NOT_ACTIVE	 0xC000029D
+#define STATUS_REMOTE_STORAGE_MEDIA_ERROR	 0xC000029E
+#define STATUS_NO_TRACKING_SERVICE	 0xC000029F
+#define STATUS_SERVER_SID_MISMATCH	 0xC00002A0
+#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE	 0xC00002A1
+#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX	 0xC00002A2
+#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED	 0xC00002A3
+#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS	 0xC00002A4
+#define STATUS_DS_BUSY	 0xC00002A5
+#define STATUS_DS_UNAVAILABLE	 0xC00002A6
+#define STATUS_DS_NO_RIDS_ALLOCATED	 0xC00002A7
+#define STATUS_DS_NO_MORE_RIDS	 0xC00002A8
+#define STATUS_DS_INCORRECT_ROLE_OWNER	 0xC00002A9
+#define STATUS_DS_RIDMGR_INIT_ERROR	 0xC00002AA
+#define STATUS_DS_OBJ_CLASS_VIOLATION	 0xC00002AB
+#define STATUS_DS_CANT_ON_NON_LEAF	 0xC00002AC
+#define STATUS_DS_CANT_ON_RDN	 0xC00002AD
+#define STATUS_DS_CANT_MOD_OBJ_CLASS	 0xC00002AE
+#define STATUS_DS_CROSS_DOM_MOVE_FAILED	 0xC00002AF
+#define STATUS_DS_GC_NOT_AVAILABLE	 0xC00002B0
+#define STATUS_DIRECTORY_SERVICE_REQUIRED	 0xC00002B1
+#define STATUS_REPARSE_ATTRIBUTE_CONFLICT	 0xC00002B2
+#define STATUS_CANT_ENABLE_DENY_ONLY	 0xC00002B3
+#define STATUS_FLOAT_MULTIPLE_FAULTS	 0xC00002B4
+#define STATUS_FLOAT_MULTIPLE_TRAPS	 0xC00002B5
+#define STATUS_DEVICE_REMOVED	 0xC00002B6
+#define STATUS_JOURNAL_DELETE_IN_PROGRESS	 0xC00002B7
+#define STATUS_JOURNAL_NOT_ACTIVE	 0xC00002B8
+#define STATUS_NOINTERFACE	 0xC00002B9
+#define STATUS_DS_ADMIN_LIMIT_EXCEEDED	 0xC00002C1
+#define STATUS_DRIVER_FAILED_SLEEP	 0xC00002C2
+#define STATUS_MUTUAL_AUTHENTICATION_FAILED	 0xC00002C3
+#define STATUS_CORRUPT_SYSTEM_FILE	 0xC00002C4
+#define STATUS_DATATYPE_MISALIGNMENT_ERROR	 0xC00002C5
+#define STATUS_WMI_READ_ONLY	 0xC00002C6
+#define STATUS_WMI_SET_FAILURE	 0xC00002C7
+#define STATUS_COMMITMENT_MINIMUM	 0xC00002C8
+#define STATUS_REG_NAT_CONSUMPTION	 0xC00002C9
+#define STATUS_TRANSPORT_FULL	 0xC00002CA
+#define STATUS_DS_SAM_INIT_FAILURE	 0xC00002CB
+#define STATUS_ONLY_IF_CONNECTED	 0xC00002CC
+#define STATUS_DS_SENSITIVE_GROUP_VIOLATION	 0xC00002CD
+#define STATUS_PNP_RESTART_ENUMERATION	 0xC00002CE
+#define STATUS_JOURNAL_ENTRY_DELETED	 0xC00002CF
+#define STATUS_DS_CANT_MOD_PRIMARYGROUPID	 0xC00002D0
+#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE	 0xC00002D1
+#define STATUS_PNP_REBOOT_REQUIRED	 0xC00002D2
+#define STATUS_POWER_STATE_INVALID	 0xC00002D3
+#define STATUS_DS_INVALID_GROUP_TYPE	 0xC00002D4
+#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN	 0xC00002D5
+#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN	 0xC00002D6
+#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER	 0xC00002D7
+#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER	 0xC00002D8
+#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER	 0xC00002D9
+#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER	 0xC00002DA
+#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER	 0xC00002DB
+#define STATUS_DS_HAVE_PRIMARY_MEMBERS	 0xC00002DC
+#define STATUS_WMI_NOT_SUPPORTED	 0xC00002DD
+#define STATUS_INSUFFICIENT_POWER	 0xC00002DE
+#define STATUS_SAM_NEED_BOOTKEY_PASSWORD	 0xC00002DF
+#define STATUS_SAM_NEED_BOOTKEY_FLOPPY	 0xC00002E0
+#define STATUS_DS_CANT_START	 0xC00002E1
+#define STATUS_DS_INIT_FAILURE	 0xC00002E2
+#define STATUS_SAM_INIT_FAILURE	 0xC00002E3
+#define STATUS_DS_GC_REQUIRED	 0xC00002E4
+#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY	 0xC00002E5
+#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS	 0xC00002E6
+#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED	 0xC00002E7
+#define STATUS_MULTIPLE_FAULT_VIOLATION	 0xC00002E8
+#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED	 0xC00002E9
+#define STATUS_CANNOT_MAKE	 0xC00002EA
+#define STATUS_SYSTEM_SHUTDOWN	 0xC00002EB
+#define STATUS_DS_INIT_FAILURE_CONSOLE	 0xC00002EC
+#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE	 0xC00002ED
+#define STATUS_UNFINISHED_CONTEXT_DELETED	 0xC00002EE
+#define STATUS_NO_TGT_REPLY	 0xC00002EF
+#define STATUS_OBJECTID_NOT_FOUND	 0xC00002F0
+#define STATUS_NO_IP_ADDRESSES	 0xC00002F1
+#define STATUS_WRONG_CREDENTIAL_HANDLE	 0xC00002F2
+#define STATUS_CRYPTO_SYSTEM_INVALID	 0xC00002F3
+#define STATUS_MAX_REFERRALS_EXCEEDED	 0xC00002F4
+#define STATUS_MUST_BE_KDC	 0xC00002F5
+#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED	 0xC00002F6
+#define STATUS_TOO_MANY_PRINCIPALS	 0xC00002F7
+#define STATUS_NO_PA_DATA	 0xC00002F8
+#define STATUS_PKINIT_NAME_MISMATCH	 0xC00002F9
+#define STATUS_SMARTCARD_LOGON_REQUIRED	 0xC00002FA
+#define STATUS_KDC_INVALID_REQUEST	 0xC00002FB
+#define STATUS_KDC_UNABLE_TO_REFER	 0xC00002FC
+#define STATUS_KDC_UNKNOWN_ETYPE	 0xC00002FD
+#define STATUS_SHUTDOWN_IN_PROGRESS	 0xC00002FE
+#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS	 0xC00002FF
+#define STATUS_NOT_SUPPORTED_ON_SBS	 0xC0000300
+#define STATUS_WMI_GUID_DISCONNECTED	 0xC0000301
+#define STATUS_WMI_ALREADY_DISABLED	 0xC0000302
+#define STATUS_WMI_ALREADY_ENABLED	 0xC0000303
+#define STATUS_MFT_TOO_FRAGMENTED	 0xC0000304
+#define STATUS_COPY_PROTECTION_FAILURE	 0xC0000305
+#define STATUS_CSS_AUTHENTICATION_FAILURE	 0xC0000306
+#define STATUS_CSS_KEY_NOT_PRESENT	 0xC0000307
+#define STATUS_CSS_KEY_NOT_ESTABLISHED	 0xC0000308
+#define STATUS_CSS_SCRAMBLED_SECTOR	 0xC0000309
+#define STATUS_CSS_REGION_MISMATCH	 0xC000030A
+#define STATUS_CSS_RESETS_EXHAUSTED	 0xC000030B
+#define STATUS_PKINIT_FAILURE	 0xC0000320
+#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE	 0xC0000321
+#define STATUS_NO_KERB_KEY	 0xC0000322
+#define STATUS_HOST_DOWN	 0xC0000350
+#define STATUS_UNSUPPORTED_PREAUTH	 0xC0000351
+#define STATUS_EFS_ALG_BLOB_TOO_BIG	 0xC0000352
+#define STATUS_PORT_NOT_SET	 0xC0000353
+#define STATUS_DEBUGGER_INACTIVE	 0xC0000354
+#define STATUS_DS_VERSION_CHECK_FAILURE	 0xC0000355
+#define STATUS_AUDITING_DISABLED	 0xC0000356
+#define STATUS_PRENT4_MACHINE_ACCOUNT	 0xC0000357
+#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER	 0xC0000358
+#define STATUS_INVALID_IMAGE_WIN_32	 0xC0000359
+#define STATUS_INVALID_IMAGE_WIN_64	 0xC000035A
+#define STATUS_BAD_BINDINGS	 0xC000035B
+#define STATUS_NETWORK_SESSION_EXPIRED	 0xC000035C
+#define STATUS_APPHELP_BLOCK	 0xC000035D
+#define STATUS_ALL_SIDS_FILTERED	 0xC000035E
+#define STATUS_NOT_SAFE_MODE_DRIVER	 0xC000035F
+#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT	 0xC0000361
+#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH	 0xC0000362
+#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER	 0xC0000363
+#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER	 0xC0000364
+#define STATUS_FAILED_DRIVER_ENTRY	 0xC0000365
+#define STATUS_DEVICE_ENUMERATION_ERROR	 0xC0000366
+#define STATUS_MOUNT_POINT_NOT_RESOLVED	 0xC0000368
+#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER	 0xC0000369
+#define STATUS_MCA_OCCURED	 0xC000036A
+#define STATUS_DRIVER_BLOCKED_CRITICAL	 0xC000036B
+#define STATUS_DRIVER_BLOCKED	 0xC000036C
+#define STATUS_DRIVER_DATABASE_ERROR	 0xC000036D
+#define STATUS_SYSTEM_HIVE_TOO_LARGE	 0xC000036E
+#define STATUS_INVALID_IMPORT_OF_NON_DLL	 0xC000036F
+#define STATUS_NO_SECRETS	 0xC0000371
+#define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY	 0xC0000372
+#define STATUS_FAILED_STACK_SWITCH	 0xC0000373
+#define STATUS_HEAP_CORRUPTION	 0xC0000374
+#define STATUS_SMARTCARD_WRONG_PIN	 0xC0000380
+#define STATUS_SMARTCARD_CARD_BLOCKED	 0xC0000381
+#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED	 0xC0000382
+#define STATUS_SMARTCARD_NO_CARD	 0xC0000383
+#define STATUS_SMARTCARD_NO_KEY_CONTAINER	 0xC0000384
+#define STATUS_SMARTCARD_NO_CERTIFICATE	 0xC0000385
+#define STATUS_SMARTCARD_NO_KEYSET	 0xC0000386
+#define STATUS_SMARTCARD_IO_ERROR	 0xC0000387
+#define STATUS_DOWNGRADE_DETECTED	 0xC0000388
+#define STATUS_SMARTCARD_CERT_REVOKED	 0xC0000389
+#define STATUS_ISSUING_CA_UNTRUSTED	 0xC000038A
+#define STATUS_REVOCATION_OFFLINE_C	 0xC000038B
+#define STATUS_PKINIT_CLIENT_FAILURE	 0xC000038C
+#define STATUS_SMARTCARD_CERT_EXPIRED	 0xC000038D
+#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD	 0xC000038E
+#define STATUS_SMARTCARD_SILENT_CONTEXT	 0xC000038F
+#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED	 0xC0000401
+#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED	 0xC0000402
+#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED	 0xC0000403
+#define STATUS_DS_NAME_NOT_UNIQUE	 0xC0000404
+#define STATUS_DS_DUPLICATE_ID_FOUND	 0xC0000405
+#define STATUS_DS_GROUP_CONVERSION_ERROR	 0xC0000406
+#define STATUS_VOLSNAP_PREPARE_HIBERNATE	 0xC0000407
+#define STATUS_USER2USER_REQUIRED	 0xC0000408
+#define STATUS_STACK_BUFFER_OVERRUN	 0xC0000409
+#define STATUS_NO_S4U_PROT_SUPPORT	 0xC000040A
+#define STATUS_CROSSREALM_DELEGATION_FAILURE	 0xC000040B
+#define STATUS_REVOCATION_OFFLINE_KDC	 0xC000040C
+#define STATUS_ISSUING_CA_UNTRUSTED_KDC	 0xC000040D
+#define STATUS_KDC_CERT_EXPIRED	 0xC000040E
+#define STATUS_KDC_CERT_REVOKED	 0xC000040F
+#define STATUS_PARAMETER_QUOTA_EXCEEDED	 0xC0000410
+#define STATUS_HIBERNATION_FAILURE	 0xC0000411
+#define STATUS_DELAY_LOAD_FAILED	 0xC0000412
+#define STATUS_AUTHENTICATION_FIREWALL_FAILED	 0xC0000413
+#define STATUS_VDM_DISALLOWED	 0xC0000414
+#define STATUS_HUNG_DISPLAY_DRIVER_THREAD	 0xC0000415
+#define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE 0xC0000416
+#define STATUS_INVALID_CRUNTIME_PARAMETER	 0xC0000417
+#define STATUS_NTLM_BLOCKED	 0xC0000418
+#define STATUS_ASSERTION_FAILURE	 0xC0000420
+#define STATUS_VERIFIER_STOP	 0xC0000421
+#define STATUS_CALLBACK_POP_STACK	 0xC0000423
+#define STATUS_INCOMPATIBLE_DRIVER_BLOCKED	 0xC0000424
+#define STATUS_HIVE_UNLOADED	 0xC0000425
+#define STATUS_COMPRESSION_DISABLED	 0xC0000426
+#define STATUS_FILE_SYSTEM_LIMITATION	 0xC0000427
+#define STATUS_INVALID_IMAGE_HASH	 0xC0000428
+#define STATUS_NOT_CAPABLE	 0xC0000429
+#define STATUS_REQUEST_OUT_OF_SEQUENCE	 0xC000042A
+#define STATUS_IMPLEMENTATION_LIMIT	 0xC000042B
+#define STATUS_ELEVATION_REQUIRED	 0xC000042C
+#define STATUS_BEYOND_VDL	 0xC0000432
+#define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS	 0xC0000433
+#define STATUS_PTE_CHANGED	 0xC0000434
+#define STATUS_PURGE_FAILED	 0xC0000435
+#define STATUS_CRED_REQUIRES_CONFIRMATION	 0xC0000440
+#define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE	 0xC0000441
+#define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER	 0xC0000442
+#define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE	 0xC0000443
+#define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE	 0xC0000444
+#define STATUS_CS_ENCRYPTION_FILE_NOT_CSE	 0xC0000445
+#define STATUS_INVALID_LABEL	 0xC0000446
+#define STATUS_DRIVER_PROCESS_TERMINATED	 0xC0000450
+#define STATUS_AMBIGUOUS_SYSTEM_DEVICE	 0xC0000451
+#define STATUS_SYSTEM_DEVICE_NOT_FOUND	 0xC0000452
+#define STATUS_RESTART_BOOT_APPLICATION	 0xC0000453
+#define STATUS_INVALID_TASK_NAME	 0xC0000500
+#define STATUS_INVALID_TASK_INDEX	 0xC0000501
+#define STATUS_THREAD_ALREADY_IN_TASK	 0xC0000502
+#define STATUS_CALLBACK_BYPASS	 0xC0000503
+#define STATUS_PORT_CLOSED	 0xC0000700
+#define STATUS_MESSAGE_LOST	 0xC0000701
+#define STATUS_INVALID_MESSAGE	 0xC0000702
+#define STATUS_REQUEST_CANCELED	 0xC0000703
+#define STATUS_RECURSIVE_DISPATCH	 0xC0000704
+#define STATUS_LPC_RECEIVE_BUFFER_EXPECTED	 0xC0000705
+#define STATUS_LPC_INVALID_CONNECTION_USAGE	 0xC0000706
+#define STATUS_LPC_REQUESTS_NOT_ALLOWED	 0xC0000707
+#define STATUS_RESOURCE_IN_USE	 0xC0000708
+#define STATUS_HARDWARE_MEMORY_ERROR	 0xC0000709
+#define STATUS_THREADPOOL_HANDLE_EXCEPTION	 0xC000070A
+#define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED	 0xC000070B
+#define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED 0xC000070C
+#define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED	 0xC000070D
+#define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED	 0xC000070E
+#define STATUS_THREADPOOL_RELEASED_DURING_OPERATION	 0xC000070F
+#define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING	 0xC0000710
+#define STATUS_APC_RETURNED_WHILE_IMPERSONATING	 0xC0000711
+#define STATUS_PROCESS_IS_PROTECTED	 0xC0000712
+#define STATUS_MCA_EXCEPTION	 0xC0000713
+#define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE	 0xC0000714
+#define STATUS_SYMLINK_CLASS_DISABLED	 0xC0000715
+#define STATUS_INVALID_IDN_NORMALIZATION	 0xC0000716
+#define STATUS_NO_UNICODE_TRANSLATION	 0xC0000717
+#define STATUS_ALREADY_REGISTERED	 0xC0000718
+#define STATUS_CONTEXT_MISMATCH	 0xC0000719
+#define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST	 0xC000071A
+#define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY	 0xC000071B
+#define STATUS_INVALID_THREAD	 0xC000071C
+#define STATUS_CALLBACK_RETURNED_TRANSACTION	 0xC000071D
+#define STATUS_CALLBACK_RETURNED_LDR_LOCK	 0xC000071E
+#define STATUS_CALLBACK_RETURNED_LANG	 0xC000071F
+#define STATUS_CALLBACK_RETURNED_PRI_BACK	 0xC0000720
+#define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY	 0xC0000721
+#define STATUS_DISK_REPAIR_DISABLED	 0xC0000800
+#define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS	 0xC0000801
+#define STATUS_DISK_QUOTA_EXCEEDED	 0xC0000802
+#define STATUS_CONTENT_BLOCKED	 0xC0000804
+#define STATUS_BAD_CLUSTERS	 0xC0000805
+#define STATUS_VOLUME_DIRTY	 0xC0000806
+#define STATUS_FILE_CHECKED_OUT	 0xC0000901
+#define STATUS_CHECKOUT_REQUIRED	 0xC0000902
+#define STATUS_BAD_FILE_TYPE	 0xC0000903
+#define STATUS_FILE_TOO_LARGE	 0xC0000904
+#define STATUS_FORMS_AUTH_REQUIRED	 0xC0000905
+#define STATUS_VIRUS_INFECTED	 0xC0000906
+#define STATUS_VIRUS_DELETED	 0xC0000907
+#define STATUS_BAD_MCFG_TABLE	 0xC0000908
+#define STATUS_WOW_ASSERTION	 0xC0009898
+#define STATUS_INVALID_SIGNATURE	 0xC000A000
+#define STATUS_HMAC_NOT_SUPPORTED	 0xC000A001
+#define STATUS_IPSEC_QUEUE_OVERFLOW	 0xC000A010
+#define STATUS_ND_QUEUE_OVERFLOW	 0xC000A011
+#define STATUS_HOPLIMIT_EXCEEDED	 0xC000A012
+#define STATUS_PROTOCOL_NOT_SUPPORTED	 0xC000A013
+#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED	 0xC000A080
+#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR	 0xC000A081
+#define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR	 0xC000A082
+#define STATUS_XML_PARSE_ERROR	 0xC000A083
+#define STATUS_XMLDSIG_ERROR	 0xC000A084
+#define STATUS_WRONG_COMPARTMENT	 0xC000A085
+#define STATUS_AUTHIP_FAILURE	 0xC000A086
+#define DBG_NO_STATE_CHANGE	 0xC0010001
+#define DBG_APP_NOT_IDLE	 0xC0010002
+#define RPC_NT_INVALID_STRING_BINDING	 0xC0020001
+#define RPC_NT_WRONG_KIND_OF_BINDING	 0xC0020002
+#define RPC_NT_INVALID_BINDING	 0xC0020003
+#define RPC_NT_PROTSEQ_NOT_SUPPORTED	 0xC0020004
+#define RPC_NT_INVALID_RPC_PROTSEQ	 0xC0020005
+#define RPC_NT_INVALID_STRING_UUID	 0xC0020006
+#define RPC_NT_INVALID_ENDPOINT_FORMAT	 0xC0020007
+#define RPC_NT_INVALID_NET_ADDR	 0xC0020008
+#define RPC_NT_NO_ENDPOINT_FOUND	 0xC0020009
+#define RPC_NT_INVALID_TIMEOUT	 0xC002000A
+#define RPC_NT_OBJECT_NOT_FOUND	 0xC002000B
+#define RPC_NT_ALREADY_REGISTERED	 0xC002000C
+#define RPC_NT_TYPE_ALREADY_REGISTERED	 0xC002000D
+#define RPC_NT_ALREADY_LISTENING	 0xC002000E
+#define RPC_NT_NO_PROTSEQS_REGISTERED	 0xC002000F
+#define RPC_NT_NOT_LISTENING	 0xC0020010
+#define RPC_NT_UNKNOWN_MGR_TYPE	 0xC0020011
+#define RPC_NT_UNKNOWN_IF	 0xC0020012
+#define RPC_NT_NO_BINDINGS	 0xC0020013
+#define RPC_NT_NO_PROTSEQS	 0xC0020014
+#define RPC_NT_CANT_CREATE_ENDPOINT	 0xC0020015
+#define RPC_NT_OUT_OF_RESOURCES	 0xC0020016
+#define RPC_NT_SERVER_UNAVAILABLE	 0xC0020017
+#define RPC_NT_SERVER_TOO_BUSY	 0xC0020018
+#define RPC_NT_INVALID_NETWORK_OPTIONS	 0xC0020019
+#define RPC_NT_NO_CALL_ACTIVE	 0xC002001A
+#define RPC_NT_CALL_FAILED	 0xC002001B
+#define RPC_NT_CALL_FAILED_DNE	 0xC002001C
+#define RPC_NT_PROTOCOL_ERROR	 0xC002001D
+#define RPC_NT_UNSUPPORTED_TRANS_SYN	 0xC002001F
+#define RPC_NT_UNSUPPORTED_TYPE	 0xC0020021
+#define RPC_NT_INVALID_TAG	 0xC0020022
+#define RPC_NT_INVALID_BOUND	 0xC0020023
+#define RPC_NT_NO_ENTRY_NAME	 0xC0020024
+#define RPC_NT_INVALID_NAME_SYNTAX	 0xC0020025
+#define RPC_NT_UNSUPPORTED_NAME_SYNTAX	 0xC0020026
+#define RPC_NT_UUID_NO_ADDRESS	 0xC0020028
+#define RPC_NT_DUPLICATE_ENDPOINT	 0xC0020029
+#define RPC_NT_UNKNOWN_AUTHN_TYPE	 0xC002002A
+#define RPC_NT_MAX_CALLS_TOO_SMALL	 0xC002002B
+#define RPC_NT_STRING_TOO_LONG	 0xC002002C
+#define RPC_NT_PROTSEQ_NOT_FOUND	 0xC002002D
+#define RPC_NT_PROCNUM_OUT_OF_RANGE	 0xC002002E
+#define RPC_NT_BINDING_HAS_NO_AUTH	 0xC002002F
+#define RPC_NT_UNKNOWN_AUTHN_SERVICE	 0xC0020030
+#define RPC_NT_UNKNOWN_AUTHN_LEVEL	 0xC0020031
+#define RPC_NT_INVALID_AUTH_IDENTITY	 0xC0020032
+#define RPC_NT_UNKNOWN_AUTHZ_SERVICE	 0xC0020033
+#define EPT_NT_INVALID_ENTRY	 0xC0020034
+#define EPT_NT_CANT_PERFORM_OP	 0xC0020035
+#define EPT_NT_NOT_REGISTERED	 0xC0020036
+#define RPC_NT_NOTHING_TO_EXPORT	 0xC0020037
+#define RPC_NT_INCOMPLETE_NAME	 0xC0020038
+#define RPC_NT_INVALID_VERS_OPTION	 0xC0020039
+#define RPC_NT_NO_MORE_MEMBERS	 0xC002003A
+#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED	 0xC002003B
+#define RPC_NT_INTERFACE_NOT_FOUND	 0xC002003C
+#define RPC_NT_ENTRY_ALREADY_EXISTS	 0xC002003D
+#define RPC_NT_ENTRY_NOT_FOUND	 0xC002003E
+#define RPC_NT_NAME_SERVICE_UNAVAILABLE	 0xC002003F
+#define RPC_NT_INVALID_NAF_ID	 0xC0020040
+#define RPC_NT_CANNOT_SUPPORT	 0xC0020041
+#define RPC_NT_NO_CONTEXT_AVAILABLE	 0xC0020042
+#define RPC_NT_INTERNAL_ERROR	 0xC0020043
+#define RPC_NT_ZERO_DIVIDE	 0xC0020044
+#define RPC_NT_ADDRESS_ERROR	 0xC0020045
+#define RPC_NT_FP_DIV_ZERO	 0xC0020046
+#define RPC_NT_FP_UNDERFLOW	 0xC0020047
+#define RPC_NT_FP_OVERFLOW	 0xC0020048
+#define RPC_NT_CALL_IN_PROGRESS	 0xC0020049
+#define RPC_NT_NO_MORE_BINDINGS	 0xC002004A
+#define RPC_NT_GROUP_MEMBER_NOT_FOUND	 0xC002004B
+#define EPT_NT_CANT_CREATE	 0xC002004C
+#define RPC_NT_INVALID_OBJECT	 0xC002004D
+#define RPC_NT_NO_INTERFACES	 0xC002004F
+#define RPC_NT_CALL_CANCELLED	 0xC0020050
+#define RPC_NT_BINDING_INCOMPLETE	 0xC0020051
+#define RPC_NT_COMM_FAILURE	 0xC0020052
+#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL	 0xC0020053
+#define RPC_NT_NO_PRINC_NAME	 0xC0020054
+#define RPC_NT_NOT_RPC_ERROR	 0xC0020055
+#define RPC_NT_SEC_PKG_ERROR	 0xC0020057
+#define RPC_NT_NOT_CANCELLED	 0xC0020058
+#define RPC_NT_INVALID_ASYNC_HANDLE	 0xC0020062
+#define RPC_NT_INVALID_ASYNC_CALL	 0xC0020063
+#define RPC_NT_PROXY_ACCESS_DENIED	 0xC0020064
+#define RPC_NT_NO_MORE_ENTRIES	 0xC0030001
+#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL	 0xC0030002
+#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE	 0xC0030003
+#define RPC_NT_SS_IN_NULL_CONTEXT	 0xC0030004
+#define RPC_NT_SS_CONTEXT_MISMATCH	 0xC0030005
+#define RPC_NT_SS_CONTEXT_DAMAGED	 0xC0030006
+#define RPC_NT_SS_HANDLES_MISMATCH	 0xC0030007
+#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE	 0xC0030008
+#define RPC_NT_NULL_REF_POINTER	 0xC0030009
+#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE	 0xC003000A
+#define RPC_NT_BYTE_COUNT_TOO_SMALL	 0xC003000B
+#define RPC_NT_BAD_STUB_DATA	 0xC003000C
+#define RPC_NT_INVALID_ES_ACTION	 0xC0030059
+#define RPC_NT_WRONG_ES_VERSION	 0xC003005A
+#define RPC_NT_WRONG_STUB_VERSION	 0xC003005B
+#define RPC_NT_INVALID_PIPE_OBJECT	 0xC003005C
+#define RPC_NT_INVALID_PIPE_OPERATION	 0xC003005D
+#define RPC_NT_WRONG_PIPE_VERSION	 0xC003005E
+#define RPC_NT_PIPE_CLOSED	 0xC003005F
+#define RPC_NT_PIPE_DISCIPLINE_ERROR	 0xC0030060
+#define RPC_NT_PIPE_EMPTY	 0xC0030061
+#define STATUS_PNP_BAD_MPS_TABLE	 0xC0040035
+#define STATUS_PNP_TRANSLATION_FAILED	 0xC0040036
+#define STATUS_PNP_IRQ_TRANSLATION_FAILED	 0xC0040037
+#define STATUS_PNP_INVALID_ID	 0xC0040038
+#define STATUS_IO_REISSUE_AS_CACHED	 0xC0040039
+#define STATUS_CTX_WINSTATION_NAME_INVALID	 0xC00A0001
+#define STATUS_CTX_INVALID_PD	 0xC00A0002
+#define STATUS_CTX_PD_NOT_FOUND	 0xC00A0003
+#define STATUS_CTX_CLOSE_PENDING	 0xC00A0006
+#define STATUS_CTX_NO_OUTBUF	 0xC00A0007
+#define STATUS_CTX_MODEM_INF_NOT_FOUND	 0xC00A0008
+#define STATUS_CTX_INVALID_MODEMNAME	 0xC00A0009
+#define STATUS_CTX_RESPONSE_ERROR	 0xC00A000A
+#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT	 0xC00A000B
+#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER	 0xC00A000C
+#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE	 0xC00A000D
+#define STATUS_CTX_MODEM_RESPONSE_BUSY	 0xC00A000E
+#define STATUS_CTX_MODEM_RESPONSE_VOICE	 0xC00A000F
+#define STATUS_CTX_TD_ERROR	 0xC00A0010
+#define STATUS_CTX_LICENSE_CLIENT_INVALID	 0xC00A0012
+#define STATUS_CTX_LICENSE_NOT_AVAILABLE	 0xC00A0013
+#define STATUS_CTX_LICENSE_EXPIRED	 0xC00A0014
+#define STATUS_CTX_WINSTATION_NOT_FOUND	 0xC00A0015
+#define STATUS_CTX_WINSTATION_NAME_COLLISION	 0xC00A0016
+#define STATUS_CTX_WINSTATION_BUSY	 0xC00A0017
+#define STATUS_CTX_BAD_VIDEO_MODE	 0xC00A0018
+#define STATUS_CTX_GRAPHICS_INVALID	 0xC00A0022
+#define STATUS_CTX_NOT_CONSOLE	 0xC00A0024
+#define STATUS_CTX_CLIENT_QUERY_TIMEOUT	 0xC00A0026
+#define STATUS_CTX_CONSOLE_DISCONNECT	 0xC00A0027
+#define STATUS_CTX_CONSOLE_CONNECT	 0xC00A0028
+#define STATUS_CTX_SHADOW_DENIED	 0xC00A002A
+#define STATUS_CTX_WINSTATION_ACCESS_DENIED	 0xC00A002B
+#define STATUS_CTX_INVALID_WD	 0xC00A002E
+#define STATUS_CTX_WD_NOT_FOUND	 0xC00A002F
+#define STATUS_CTX_SHADOW_INVALID	 0xC00A0030
+#define STATUS_CTX_SHADOW_DISABLED	 0xC00A0031
+#define STATUS_RDP_PROTOCOL_ERROR	 0xC00A0032
+#define STATUS_CTX_CLIENT_LICENSE_NOT_SET	 0xC00A0033
+#define STATUS_CTX_CLIENT_LICENSE_IN_USE	 0xC00A0034
+#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE	 0xC00A0035
+#define STATUS_CTX_SHADOW_NOT_RUNNING	 0xC00A0036
+#define STATUS_CTX_LOGON_DISABLED	 0xC00A0037
+#define STATUS_CTX_SECURITY_LAYER_ERROR	 0xC00A0038
+#define STATUS_TS_INCOMPATIBLE_SESSIONS	 0xC00A0039
+#define STATUS_MUI_FILE_NOT_FOUND	 0xC00B0001
+#define STATUS_MUI_INVALID_FILE	 0xC00B0002
+#define STATUS_MUI_INVALID_RC_CONFIG	 0xC00B0003
+#define STATUS_MUI_INVALID_LOCALE_NAME	 0xC00B0004
+#define STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME	 0xC00B0005
+#define STATUS_MUI_FILE_NOT_LOADED	 0xC00B0006
+#define STATUS_RESOURCE_ENUM_USER_STOP	 0xC00B0007
+#define STATUS_CLUSTER_INVALID_NODE	 0xC0130001
+#define STATUS_CLUSTER_NODE_EXISTS	 0xC0130002
+#define STATUS_CLUSTER_JOIN_IN_PROGRESS	 0xC0130003
+#define STATUS_CLUSTER_NODE_NOT_FOUND	 0xC0130004
+#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND	 0xC0130005
+#define STATUS_CLUSTER_NETWORK_EXISTS	 0xC0130006
+#define STATUS_CLUSTER_NETWORK_NOT_FOUND	 0xC0130007
+#define STATUS_CLUSTER_NETINTERFACE_EXISTS	 0xC0130008
+#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND	 0xC0130009
+#define STATUS_CLUSTER_INVALID_REQUEST	 0xC013000A
+#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER	 0xC013000B
+#define STATUS_CLUSTER_NODE_DOWN	 0xC013000C
+#define STATUS_CLUSTER_NODE_UNREACHABLE	 0xC013000D
+#define STATUS_CLUSTER_NODE_NOT_MEMBER	 0xC013000E
+#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS	 0xC013000F
+#define STATUS_CLUSTER_INVALID_NETWORK	 0xC0130010
+#define STATUS_CLUSTER_NO_NET_ADAPTERS	 0xC0130011
+#define STATUS_CLUSTER_NODE_UP	 0xC0130012
+#define STATUS_CLUSTER_NODE_PAUSED	 0xC0130013
+#define STATUS_CLUSTER_NODE_NOT_PAUSED	 0xC0130014
+#define STATUS_CLUSTER_NO_SECURITY_CONTEXT	 0xC0130015
+#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL	 0xC0130016
+#define STATUS_CLUSTER_POISONED	 0xC0130017
+#define STATUS_ACPI_INVALID_OPCODE	 0xC0140001
+#define STATUS_ACPI_STACK_OVERFLOW	 0xC0140002
+#define STATUS_ACPI_ASSERT_FAILED	 0xC0140003
+#define STATUS_ACPI_INVALID_INDEX	 0xC0140004
+#define STATUS_ACPI_INVALID_ARGUMENT	 0xC0140005
+#define STATUS_ACPI_FATAL	 0xC0140006
+#define STATUS_ACPI_INVALID_SUPERNAME	 0xC0140007
+#define STATUS_ACPI_INVALID_ARGTYPE	 0xC0140008
+#define STATUS_ACPI_INVALID_OBJTYPE	 0xC0140009
+#define STATUS_ACPI_INVALID_TARGETTYPE	 0xC014000A
+#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT	 0xC014000B
+#define STATUS_ACPI_ADDRESS_NOT_MAPPED	 0xC014000C
+#define STATUS_ACPI_INVALID_EVENTTYPE	 0xC014000D
+#define STATUS_ACPI_HANDLER_COLLISION	 0xC014000E
+#define STATUS_ACPI_INVALID_DATA	 0xC014000F
+#define STATUS_ACPI_INVALID_REGION	 0xC0140010
+#define STATUS_ACPI_INVALID_ACCESS_SIZE	 0xC0140011
+#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK	 0xC0140012
+#define STATUS_ACPI_ALREADY_INITIALIZED	 0xC0140013
+#define STATUS_ACPI_NOT_INITIALIZED	 0xC0140014
+#define STATUS_ACPI_INVALID_MUTEX_LEVEL	 0xC0140015
+#define STATUS_ACPI_MUTEX_NOT_OWNED	 0xC0140016
+#define STATUS_ACPI_MUTEX_NOT_OWNER	 0xC0140017
+#define STATUS_ACPI_RS_ACCESS	 0xC0140018
+#define STATUS_ACPI_INVALID_TABLE	 0xC0140019
+#define STATUS_ACPI_REG_HANDLER_FAILED	 0xC0140020
+#define STATUS_ACPI_POWER_REQUEST_FAILED	 0xC0140021
+#define STATUS_SXS_SECTION_NOT_FOUND	 0xC0150001
+#define STATUS_SXS_CANT_GEN_ACTCTX	 0xC0150002
+#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT	 0xC0150003
+#define STATUS_SXS_ASSEMBLY_NOT_FOUND	 0xC0150004
+#define STATUS_SXS_MANIFEST_FORMAT_ERROR	 0xC0150005
+#define STATUS_SXS_MANIFEST_PARSE_ERROR	 0xC0150006
+#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED	 0xC0150007
+#define STATUS_SXS_KEY_NOT_FOUND	 0xC0150008
+#define STATUS_SXS_VERSION_CONFLICT	 0xC0150009
+#define STATUS_SXS_WRONG_SECTION_TYPE	 0xC015000A
+#define STATUS_SXS_THREAD_QUERIES_DISABLED	 0xC015000B
+#define STATUS_SXS_ASSEMBLY_MISSING	 0xC015000C
+#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET	 0xC015000E
+#define STATUS_SXS_EARLY_DEACTIVATION	 0xC015000F
+#define STATUS_SXS_INVALID_DEACTIVATION	 0xC0150010
+#define STATUS_SXS_MULTIPLE_DEACTIVATION	 0xC0150011
+#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY	 0xC0150012
+#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED	 0xC0150013
+#define STATUS_SXS_CORRUPT_ACTIVATION_STACK	 0xC0150014
+#define STATUS_SXS_CORRUPTION	 0xC0150015
+#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE	 0xC0150016
+#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME	 0xC0150017
+#define STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE	 0xC0150018
+#define STATUS_SXS_IDENTITY_PARSE_ERROR	 0xC0150019
+#define STATUS_SXS_COMPONENT_STORE_CORRUPT	 0xC015001A
+#define STATUS_SXS_FILE_HASH_MISMATCH	 0xC015001B
+#define STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT 0xC015001C
+#define STATUS_SXS_IDENTITIES_DIFFERENT	 0xC015001D
+#define STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT	 0xC015001E
+#define STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY	 0xC015001F
+#define STATUS_ADVANCED_INSTALLER_FAILED	 0xC0150020
+#define STATUS_XML_ENCODING_MISMATCH	 0xC0150021
+#define STATUS_SXS_MANIFEST_TOO_BIG	 0xC0150022
+#define STATUS_SXS_SETTING_NOT_REGISTERED	 0xC0150023
+#define STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE	 0xC0150024
+#define STATUS_SMI_PRIMITIVE_INSTALLER_FAILED	 0xC0150025
+#define STATUS_GENERIC_COMMAND_FAILED	 0xC0150026
+#define STATUS_SXS_FILE_HASH_MISSING	 0xC0150027
+#define STATUS_TRANSACTIONAL_CONFLICT	 0xC0190001
+#define STATUS_INVALID_TRANSACTION	 0xC0190002
+#define STATUS_TRANSACTION_NOT_ACTIVE	 0xC0190003
+#define STATUS_TM_INITIALIZATION_FAILED	 0xC0190004
+#define STATUS_RM_NOT_ACTIVE	 0xC0190005
+#define STATUS_RM_METADATA_CORRUPT	 0xC0190006
+#define STATUS_TRANSACTION_NOT_JOINED	 0xC0190007
+#define STATUS_DIRECTORY_NOT_RM	 0xC0190008
+#define STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE	 0xC019000A
+#define STATUS_LOG_RESIZE_INVALID_SIZE	 0xC019000B
+#define STATUS_REMOTE_FILE_VERSION_MISMATCH	 0xC019000C
+#define STATUS_CRM_PROTOCOL_ALREADY_EXISTS	 0xC019000F
+#define STATUS_TRANSACTION_PROPAGATION_FAILED	 0xC0190010
+#define STATUS_CRM_PROTOCOL_NOT_FOUND	 0xC0190011
+#define STATUS_TRANSACTION_SUPERIOR_EXISTS	 0xC0190012
+#define STATUS_TRANSACTION_REQUEST_NOT_VALID	 0xC0190013
+#define STATUS_TRANSACTION_NOT_REQUESTED	 0xC0190014
+#define STATUS_TRANSACTION_ALREADY_ABORTED	 0xC0190015
+#define STATUS_TRANSACTION_ALREADY_COMMITTED	 0xC0190016
+#define STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER	 0xC0190017
+#define STATUS_CURRENT_TRANSACTION_NOT_VALID	 0xC0190018
+#define STATUS_LOG_GROWTH_FAILED	 0xC0190019
+#define STATUS_OBJECT_NO_LONGER_EXISTS	 0xC0190021
+#define STATUS_STREAM_MINIVERSION_NOT_FOUND	 0xC0190022
+#define STATUS_STREAM_MINIVERSION_NOT_VALID	 0xC0190023
+#define STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION 0xC0190024
+#define STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT	 0xC0190025
+#define STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS	 0xC0190026
+#define STATUS_HANDLE_NO_LONGER_VALID	 0xC0190028
+#define STATUS_LOG_CORRUPTION_DETECTED	 0xC0190030
+#define STATUS_RM_DISCONNECTED	 0xC0190032
+#define STATUS_ENLISTMENT_NOT_SUPERIOR	 0xC0190033
+#define STATUS_FILE_IDENTITY_NOT_PERSISTENT	 0xC0190036
+#define STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY	 0xC0190037
+#define STATUS_CANT_CROSS_RM_BOUNDARY	 0xC0190038
+#define STATUS_TXF_DIR_NOT_EMPTY	 0xC0190039
+#define STATUS_INDOUBT_TRANSACTIONS_EXIST	 0xC019003A
+#define STATUS_TM_VOLATILE	 0xC019003B
+#define STATUS_ROLLBACK_TIMER_EXPIRED	 0xC019003C
+#define STATUS_TXF_ATTRIBUTE_CORRUPT	 0xC019003D
+#define STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION	 0xC019003E
+#define STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED	 0xC019003F
+#define STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE	 0xC0190040
+#define STATUS_TRANSACTION_REQUIRED_PROMOTION	 0xC0190043
+#define STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION	 0xC0190044
+#define STATUS_TRANSACTIONS_NOT_FROZEN	 0xC0190045
+#define STATUS_TRANSACTION_FREEZE_IN_PROGRESS	 0xC0190046
+#define STATUS_NOT_SNAPSHOT_VOLUME	 0xC0190047
+#define STATUS_NO_SAVEPOINT_WITH_OPEN_FILES	 0xC0190048
+#define STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION	 0xC0190049
+#define STATUS_TM_IDENTITY_MISMATCH	 0xC019004A
+#define STATUS_FLOATED_SECTION	 0xC019004B
+#define STATUS_CANNOT_ACCEPT_TRANSACTED_WORK	 0xC019004C
+#define STATUS_CANNOT_ABORT_TRANSACTIONS	 0xC019004D
+#define STATUS_TRANSACTION_NOT_FOUND	 0xC019004E
+#define STATUS_RESOURCEMANAGER_NOT_FOUND	 0xC019004F
+#define STATUS_ENLISTMENT_NOT_FOUND	 0xC0190050
+#define STATUS_TRANSACTIONMANAGER_NOT_FOUND	 0xC0190051
+#define STATUS_TRANSACTIONMANAGER_NOT_ONLINE	 0xC0190052
+#define STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION	 0xC0190053
+#define STATUS_TRANSACTION_NOT_ROOT	 0xC0190054
+#define STATUS_TRANSACTION_OBJECT_EXPIRED	 0xC0190055
+#define STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION	 0xC0190056
+#define STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED	 0xC0190057
+#define STATUS_TRANSACTION_RECORD_TOO_LONG	 0xC0190058
+#define STATUS_NO_LINK_TRACKING_IN_TRANSACTION	 0xC0190059
+#define STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION	 0xC019005A
+#define STATUS_TRANSACTION_INTEGRITY_VIOLATED	 0xC019005B
+#define STATUS_LOG_SECTOR_INVALID	 0xC01A0001
+#define STATUS_LOG_SECTOR_PARITY_INVALID	 0xC01A0002
+#define STATUS_LOG_SECTOR_REMAPPED	 0xC01A0003
+#define STATUS_LOG_BLOCK_INCOMPLETE	 0xC01A0004
+#define STATUS_LOG_INVALID_RANGE	 0xC01A0005
+#define STATUS_LOG_BLOCKS_EXHAUSTED	 0xC01A0006
+#define STATUS_LOG_READ_CONTEXT_INVALID	 0xC01A0007
+#define STATUS_LOG_RESTART_INVALID	 0xC01A0008
+#define STATUS_LOG_BLOCK_VERSION	 0xC01A0009
+#define STATUS_LOG_BLOCK_INVALID	 0xC01A000A
+#define STATUS_LOG_READ_MODE_INVALID	 0xC01A000B
+#define STATUS_LOG_METADATA_CORRUPT	 0xC01A000D
+#define STATUS_LOG_METADATA_INVALID	 0xC01A000E
+#define STATUS_LOG_METADATA_INCONSISTENT	 0xC01A000F
+#define STATUS_LOG_RESERVATION_INVALID	 0xC01A0010
+#define STATUS_LOG_CANT_DELETE	 0xC01A0011
+#define STATUS_LOG_CONTAINER_LIMIT_EXCEEDED	 0xC01A0012
+#define STATUS_LOG_START_OF_LOG	 0xC01A0013
+#define STATUS_LOG_POLICY_ALREADY_INSTALLED	 0xC01A0014
+#define STATUS_LOG_POLICY_NOT_INSTALLED	 0xC01A0015
+#define STATUS_LOG_POLICY_INVALID	 0xC01A0016
+#define STATUS_LOG_POLICY_CONFLICT	 0xC01A0017
+#define STATUS_LOG_PINNED_ARCHIVE_TAIL	 0xC01A0018
+#define STATUS_LOG_RECORD_NONEXISTENT	 0xC01A0019
+#define STATUS_LOG_RECORDS_RESERVED_INVALID	 0xC01A001A
+#define STATUS_LOG_SPACE_RESERVED_INVALID	 0xC01A001B
+#define STATUS_LOG_TAIL_INVALID	 0xC01A001C
+#define STATUS_LOG_FULL	 0xC01A001D
+#define STATUS_LOG_MULTIPLEXED	 0xC01A001E
+#define STATUS_LOG_DEDICATED	 0xC01A001F
+#define STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS	 0xC01A0020
+#define STATUS_LOG_ARCHIVE_IN_PROGRESS	 0xC01A0021
+#define STATUS_LOG_EPHEMERAL	 0xC01A0022
+#define STATUS_LOG_NOT_ENOUGH_CONTAINERS	 0xC01A0023
+#define STATUS_LOG_CLIENT_ALREADY_REGISTERED	 0xC01A0024
+#define STATUS_LOG_CLIENT_NOT_REGISTERED	 0xC01A0025
+#define STATUS_LOG_FULL_HANDLER_IN_PROGRESS	 0xC01A0026
+#define STATUS_LOG_CONTAINER_READ_FAILED	 0xC01A0027
+#define STATUS_LOG_CONTAINER_WRITE_FAILED	 0xC01A0028
+#define STATUS_LOG_CONTAINER_OPEN_FAILED	 0xC01A0029
+#define STATUS_LOG_CONTAINER_STATE_INVALID	 0xC01A002A
+#define STATUS_LOG_STATE_INVALID	 0xC01A002B
+#define STATUS_LOG_PINNED	 0xC01A002C
+#define STATUS_LOG_METADATA_FLUSH_FAILED	 0xC01A002D
+#define STATUS_LOG_INCONSISTENT_SECURITY	 0xC01A002E
+#define STATUS_LOG_APPENDED_FLUSH_FAILED	 0xC01A002F
+#define STATUS_LOG_PINNED_RESERVATION	 0xC01A0030
+#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD	 0xC01B00EA
+#define STATUS_FLT_NO_HANDLER_DEFINED	 0xC01C0001
+#define STATUS_FLT_CONTEXT_ALREADY_DEFINED	 0xC01C0002
+#define STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST	 0xC01C0003
+#define STATUS_FLT_DISALLOW_FAST_IO	 0xC01C0004
+#define STATUS_FLT_INVALID_NAME_REQUEST	 0xC01C0005
+#define STATUS_FLT_NOT_SAFE_TO_POST_OPERATION	 0xC01C0006
+#define STATUS_FLT_NOT_INITIALIZED	 0xC01C0007
+#define STATUS_FLT_FILTER_NOT_READY	 0xC01C0008
+#define STATUS_FLT_POST_OPERATION_CLEANUP	 0xC01C0009
+#define STATUS_FLT_INTERNAL_ERROR	 0xC01C000A
+#define STATUS_FLT_DELETING_OBJECT	 0xC01C000B
+#define STATUS_FLT_MUST_BE_NONPAGED_POOL	 0xC01C000C
+#define STATUS_FLT_DUPLICATE_ENTRY	 0xC01C000D
+#define STATUS_FLT_CBDQ_DISABLED	 0xC01C000E
+#define STATUS_FLT_DO_NOT_ATTACH	 0xC01C000F
+#define STATUS_FLT_DO_NOT_DETACH	 0xC01C0010
+#define STATUS_FLT_INSTANCE_ALTITUDE_COLLISION	 0xC01C0011
+#define STATUS_FLT_INSTANCE_NAME_COLLISION	 0xC01C0012
+#define STATUS_FLT_FILTER_NOT_FOUND	 0xC01C0013
+#define STATUS_FLT_VOLUME_NOT_FOUND	 0xC01C0014
+#define STATUS_FLT_INSTANCE_NOT_FOUND	 0xC01C0015
+#define STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND	 0xC01C0016
+#define STATUS_FLT_INVALID_CONTEXT_REGISTRATION	 0xC01C0017
+#define STATUS_FLT_NAME_CACHE_MISS	 0xC01C0018
+#define STATUS_FLT_NO_DEVICE_OBJECT	 0xC01C0019
+#define STATUS_FLT_VOLUME_ALREADY_MOUNTED	 0xC01C001A
+#define STATUS_FLT_ALREADY_ENLISTED	 0xC01C001B
+#define STATUS_FLT_CONTEXT_ALREADY_LINKED	 0xC01C001C
+#define STATUS_FLT_NO_WAITER_FOR_REPLY	 0xC01C0020
+#define STATUS_MONITOR_NO_DESCRIPTOR	 0xC01D0001
+#define STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT	 0xC01D0002
+#define STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM	 0xC01D0003
+#define STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK	 0xC01D0004
+#define STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED	 0xC01D0005
+#define STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK	 0xC01D0006
+#define STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK	 0xC01D0007
+#define STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA	 0xC01D0008
+#define STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK	 0xC01D0009
+#define STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER	 0xC01E0000
+#define STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER	 0xC01E0001
+#define STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER	 0xC01E0002
+#define STATUS_GRAPHICS_ADAPTER_WAS_RESET	 0xC01E0003
+#define STATUS_GRAPHICS_INVALID_DRIVER_MODEL	 0xC01E0004
+#define STATUS_GRAPHICS_PRESENT_MODE_CHANGED	 0xC01E0005
+#define STATUS_GRAPHICS_PRESENT_OCCLUDED	 0xC01E0006
+#define STATUS_GRAPHICS_PRESENT_DENIED	 0xC01E0007
+#define STATUS_GRAPHICS_CANNOTCOLORCONVERT	 0xC01E0008
+#define STATUS_GRAPHICS_NO_VIDEO_MEMORY	 0xC01E0100
+#define STATUS_GRAPHICS_CANT_LOCK_MEMORY	 0xC01E0101
+#define STATUS_GRAPHICS_ALLOCATION_BUSY	 0xC01E0102
+#define STATUS_GRAPHICS_TOO_MANY_REFERENCES	 0xC01E0103
+#define STATUS_GRAPHICS_TRY_AGAIN_LATER	 0xC01E0104
+#define STATUS_GRAPHICS_TRY_AGAIN_NOW	 0xC01E0105
+#define STATUS_GRAPHICS_ALLOCATION_INVALID	 0xC01E0106
+#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE	 0xC01E0107
+#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED	 0xC01E0108
+#define STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION	 0xC01E0109
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE	 0xC01E0110
+#define STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION	 0xC01E0111
+#define STATUS_GRAPHICS_ALLOCATION_CLOSED	 0xC01E0112
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE	 0xC01E0113
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE	 0xC01E0114
+#define STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE	 0xC01E0115
+#define STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST	 0xC01E0116
+#define STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE	 0xC01E0200
+#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY	 0xC01E0300
+#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED	 0xC01E0301
+#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED	 0xC01E0302
+#define STATUS_GRAPHICS_INVALID_VIDPN	 0xC01E0303
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE	 0xC01E0304
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET	 0xC01E0305
+#define STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED	 0xC01E0306
+#define STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET	 0xC01E0308
+#define STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET	 0xC01E0309
+#define STATUS_GRAPHICS_INVALID_FREQUENCY	 0xC01E030A
+#define STATUS_GRAPHICS_INVALID_ACTIVE_REGION	 0xC01E030B
+#define STATUS_GRAPHICS_INVALID_TOTAL_REGION	 0xC01E030C
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE	 0xC01E0310
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE	 0xC01E0311
+#define STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET	 0xC01E0312
+#define STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY	 0xC01E0313
+#define STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET	 0xC01E0314
+#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET	 0xC01E0315
+#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET	 0xC01E0316
+#define STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET	 0xC01E0317
+#define STATUS_GRAPHICS_TARGET_ALREADY_IN_SET	 0xC01E0318
+#define STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH	 0xC01E0319
+#define STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY	 0xC01E031A
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET	 0xC01E031B
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE	 0xC01E031C
+#define STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET	 0xC01E031D
+#define STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET	 0xC01E031F
+#define STATUS_GRAPHICS_STALE_MODESET	 0xC01E0320
+#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET	 0xC01E0321
+#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE	 0xC01E0322
+#define STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN	 0xC01E0323
+#define STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE	 0xC01E0324
+#define STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION	0xC01E0325
+#define STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES	 0xC01E0326
+#define STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY	 0xC01E0327
+#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE	 0xC01E0328
+#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET	 0xC01E0329
+#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET	 0xC01E032A
+#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR	 0xC01E032B
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET	 0xC01E032C
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET	 0xC01E032D
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE	 0xC01E032E
+#define STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE	 0xC01E032F
+#define STATUS_GRAPHICS_RESOURCES_NOT_RELATED	 0xC01E0330
+#define STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE	 0xC01E0331
+#define STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE	 0xC01E0332
+#define STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET	 0xC01E0333
+#define STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER 0xC01E0334
+#define STATUS_GRAPHICS_NO_VIDPNMGR	 0xC01E0335
+#define STATUS_GRAPHICS_NO_ACTIVE_VIDPN	 0xC01E0336
+#define STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY	 0xC01E0337
+#define STATUS_GRAPHICS_MONITOR_NOT_CONNECTED	 0xC01E0338
+#define STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY	 0xC01E0339
+#define STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE	 0xC01E033A
+#define STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE	 0xC01E033B
+#define STATUS_GRAPHICS_INVALID_STRIDE	 0xC01E033C
+#define STATUS_GRAPHICS_INVALID_PIXELFORMAT	 0xC01E033D
+#define STATUS_GRAPHICS_INVALID_COLORBASIS	 0xC01E033E
+#define STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE	 0xC01E033F
+#define STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY	 0xC01E0340
+#define STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT	 0xC01E0341
+#define STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE	 0xC01E0342
+#define STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN	 0xC01E0343
+#define STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL	 0xC01E0344
+#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION 0xC01E0345
+#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED 0xC01E0346
+#define STATUS_GRAPHICS_INVALID_GAMMA_RAMP	 0xC01E0347
+#define STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED	 0xC01E0348
+#define STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED	 0xC01E0349
+#define STATUS_GRAPHICS_MODE_NOT_IN_MODESET	 0xC01E034A
+#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON 0xC01E034D
+#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE	 0xC01E034E
+#define STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE	 0xC01E034F
+#define STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS	 0xC01E0350
+#define STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING	 0xC01E0352
+#define STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED	 0xC01E0353
+#define STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS	 0xC01E0354
+#define STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT	 0xC01E0355
+#define STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM	 0xC01E0356
+#define STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN	 0xC01E0357
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT 0xC01E0358
+#define STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED	 0xC01E0359
+#define STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION	 0xC01E035A
+#define STATUS_GRAPHICS_INVALID_CLIENT_TYPE	 0xC01E035B
+#define STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET	 0xC01E035C
+#define STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED	 0xC01E0400
+#define STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED	 0xC01E0401
+#define STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER	 0xC01E0430
+#define STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED	 0xC01E0431
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED	 0xC01E0432
+#define STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY	 0xC01E0433
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED	 0xC01E0434
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON	 0xC01E0435
+#define STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE	 0xC01E0436
+#define STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER	 0xC01E0438
+#define STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED	 0xC01E043B
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS 0xC01E051C
+#define STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST	 0xC01E051D
+#define STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR	 0xC01E051E
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS 0xC01E051F
+#define STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED	 0xC01E0520
+#define STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST	 0xC01E0521
+#define STATUS_GRAPHICS_OPM_NOT_SUPPORTED	 0xC01E0500
+#define STATUS_GRAPHICS_COPP_NOT_SUPPORTED	 0xC01E0501
+#define STATUS_GRAPHICS_UAB_NOT_SUPPORTED	 0xC01E0502
+#define STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS	 0xC01E0503
+#define STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL	 0xC01E0504
+#define STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST	 0xC01E0505
+#define STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME 0xC01E0506
+#define STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP 0xC01E0507
+#define STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED	 0xC01E0508
+#define STATUS_GRAPHICS_OPM_INVALID_POINTER	 0xC01E050A
+#define STATUS_GRAPHICS_OPM_INTERNAL_ERROR	 0xC01E050B
+#define STATUS_GRAPHICS_OPM_INVALID_HANDLE	 0xC01E050C
+#define STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE 0xC01E050D
+#define STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH	 0xC01E050E
+#define STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED	 0xC01E050F
+#define STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED	 0xC01E0510
+#define STATUS_GRAPHICS_PVP_HFS_FAILED	 0xC01E0511
+#define STATUS_GRAPHICS_OPM_INVALID_SRM	 0xC01E0512
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP	 0xC01E0513
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP	 0xC01E0514
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA	 0xC01E0515
+#define STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET	 0xC01E0516
+#define STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH	 0xC01E0517
+#define STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE	 0xC01E0518
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS	 0xC01E051A
+#define STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS	 0xC01E051B
+#define STATUS_GRAPHICS_I2C_NOT_SUPPORTED	 0xC01E0580
+#define STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST	 0xC01E0581
+#define STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA	 0xC01E0582
+#define STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA	 0xC01E0583
+#define STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED	 0xC01E0584
+#define STATUS_GRAPHICS_DDCCI_INVALID_DATA	 0xC01E0585
+#define STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE 0xC01E0586
+#define STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING	 0xC01E0587
+#define STATUS_GRAPHICS_MCA_INTERNAL_ERROR	 0xC01E0588
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND	 0xC01E0589
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH	 0xC01E058A
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM	 0xC01E058B
+#define STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE	 0xC01E058C
+#define STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS	 0xC01E058D
+#define STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED	 0xC01E05E0
+#define STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME	 0xC01E05E1
+#define STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP	 0xC01E05E2
+#define STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED	 0xC01E05E3
+#define STATUS_GRAPHICS_INVALID_POINTER	 0xC01E05E4
+#define STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE 0xC01E05E5
+#define STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL	 0xC01E05E6
+#define STATUS_GRAPHICS_INTERNAL_ERROR	 0xC01E05E7
+#define STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS	 0xC01E05E8
+#define STATUS_FVE_LOCKED_VOLUME	 0xC0210000
+#define STATUS_FVE_NOT_ENCRYPTED	 0xC0210001
+#define STATUS_FVE_BAD_INFORMATION	 0xC0210002
+#define STATUS_FVE_TOO_SMALL	 0xC0210003
+#define STATUS_FVE_FAILED_WRONG_FS	 0xC0210004
+#define STATUS_FVE_FAILED_BAD_FS	 0xC0210005
+#define STATUS_FVE_FS_NOT_EXTENDED	 0xC0210006
+#define STATUS_FVE_FS_MOUNTED	 0xC0210007
+#define STATUS_FVE_NO_LICENSE	 0xC0210008
+#define STATUS_FVE_ACTION_NOT_ALLOWED	 0xC0210009
+#define STATUS_FVE_BAD_DATA	 0xC021000A
+#define STATUS_FVE_VOLUME_NOT_BOUND	 0xC021000B
+#define STATUS_FVE_NOT_DATA_VOLUME	 0xC021000C
+#define STATUS_FVE_CONV_READ_ERROR	 0xC021000D
+#define STATUS_FVE_CONV_WRITE_ERROR	 0xC021000E
+#define STATUS_FVE_OVERLAPPED_UPDATE	 0xC021000F
+#define STATUS_FVE_FAILED_SECTOR_SIZE	 0xC0210010
+#define STATUS_FVE_FAILED_AUTHENTICATION	 0xC0210011
+#define STATUS_FVE_NOT_OS_VOLUME	 0xC0210012
+#define STATUS_FVE_KEYFILE_NOT_FOUND	 0xC0210013
+#define STATUS_FVE_KEYFILE_INVALID	 0xC0210014
+#define STATUS_FVE_KEYFILE_NO_VMK	 0xC0210015
+#define STATUS_FVE_TPM_DISABLED	 0xC0210016
+#define STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO	 0xC0210017
+#define STATUS_FVE_TPM_INVALID_PCR	 0xC0210018
+#define STATUS_FVE_TPM_NO_VMK	 0xC0210019
+#define STATUS_FVE_PIN_INVALID	 0xC021001A
+#define STATUS_FVE_AUTH_INVALID_APPLICATION	 0xC021001B
+#define STATUS_FVE_AUTH_INVALID_CONFIG	 0xC021001C
+#define STATUS_FVE_DEBUGGER_ENABLED	 0xC021001D
+#define STATUS_FVE_DRY_RUN_FAILED	 0xC021001E
+#define STATUS_FVE_BAD_METADATA_POINTER	 0xC021001F
+#define STATUS_FVE_OLD_METADATA_COPY	 0xC0210020
+#define STATUS_FVE_REBOOT_REQUIRED	 0xC0210021
+#define STATUS_FVE_RAW_ACCESS	 0xC0210022
+#define STATUS_FVE_RAW_BLOCKED	 0xC0210023
+#define STATUS_FWP_CALLOUT_NOT_FOUND	 0xC0220001
+#define STATUS_FWP_CONDITION_NOT_FOUND	 0xC0220002
+#define STATUS_FWP_FILTER_NOT_FOUND	 0xC0220003
+#define STATUS_FWP_LAYER_NOT_FOUND	 0xC0220004
+#define STATUS_FWP_PROVIDER_NOT_FOUND	 0xC0220005
+#define STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND	 0xC0220006
+#define STATUS_FWP_SUBLAYER_NOT_FOUND	 0xC0220007
+#define STATUS_FWP_NOT_FOUND	 0xC0220008
+#define STATUS_FWP_ALREADY_EXISTS	 0xC0220009
+#define STATUS_FWP_IN_USE	 0xC022000A
+#define STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS	 0xC022000B
+#define STATUS_FWP_WRONG_SESSION	 0xC022000C
+#define STATUS_FWP_NO_TXN_IN_PROGRESS	 0xC022000D
+#define STATUS_FWP_TXN_IN_PROGRESS	 0xC022000E
+#define STATUS_FWP_TXN_ABORTED	 0xC022000F
+#define STATUS_FWP_SESSION_ABORTED	 0xC0220010
+#define STATUS_FWP_INCOMPATIBLE_TXN	 0xC0220011
+#define STATUS_FWP_TIMEOUT	 0xC0220012
+#define STATUS_FWP_NET_EVENTS_DISABLED	 0xC0220013
+#define STATUS_FWP_INCOMPATIBLE_LAYER	 0xC0220014
+#define STATUS_FWP_KM_CLIENTS_ONLY	 0xC0220015
+#define STATUS_FWP_LIFETIME_MISMATCH	 0xC0220016
+#define STATUS_FWP_BUILTIN_OBJECT	 0xC0220017
+#define STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS	 0xC0220018
+#define STATUS_FWP_TOO_MANY_CALLOUTS	 0xC0220018
+#define STATUS_FWP_NOTIFICATION_DROPPED	 0xC0220019
+#define STATUS_FWP_TRAFFIC_MISMATCH	 0xC022001A
+#define STATUS_FWP_INCOMPATIBLE_SA_STATE	 0xC022001B
+#define STATUS_FWP_NULL_POINTER	 0xC022001C
+#define STATUS_FWP_INVALID_ENUMERATOR	 0xC022001D
+#define STATUS_FWP_INVALID_FLAGS	 0xC022001E
+#define STATUS_FWP_INVALID_NET_MASK	 0xC022001F
+#define STATUS_FWP_INVALID_RANGE	 0xC0220020
+#define STATUS_FWP_INVALID_INTERVAL	 0xC0220021
+#define STATUS_FWP_ZERO_LENGTH_ARRAY	 0xC0220022
+#define STATUS_FWP_NULL_DISPLAY_NAME	 0xC0220023
+#define STATUS_FWP_INVALID_ACTION_TYPE	 0xC0220024
+#define STATUS_FWP_INVALID_WEIGHT	 0xC0220025
+#define STATUS_FWP_MATCH_TYPE_MISMATCH	 0xC0220026
+#define STATUS_FWP_TYPE_MISMATCH	 0xC0220027
+#define STATUS_FWP_OUT_OF_BOUNDS	 0xC0220028
+#define STATUS_FWP_RESERVED	 0xC0220029
+#define STATUS_FWP_DUPLICATE_CONDITION	 0xC022002A
+#define STATUS_FWP_DUPLICATE_KEYMOD	 0xC022002B
+#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER	 0xC022002C
+#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER	 0xC022002D
+#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER	 0xC022002E
+#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT	 0xC022002F
+#define STATUS_FWP_INCOMPATIBLE_AUTH_METHOD	 0xC0220030
+#define STATUS_FWP_INCOMPATIBLE_DH_GROUP	 0xC0220031
+#define STATUS_FWP_EM_NOT_SUPPORTED	 0xC0220032
+#define STATUS_FWP_NEVER_MATCH	 0xC0220033
+#define STATUS_FWP_PROVIDER_CONTEXT_MISMATCH	 0xC0220034
+#define STATUS_FWP_INVALID_PARAMETER	 0xC0220035
+#define STATUS_FWP_TOO_MANY_SUBLAYERS	 0xC0220036
+#define STATUS_FWP_CALLOUT_NOTIFICATION_FAILED	 0xC0220037
+#define STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG	 0xC0220038
+#define STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG	 0xC0220039
+#define STATUS_FWP_TCPIP_NOT_READY	 0xC0220100
+#define STATUS_FWP_INJECT_HANDLE_CLOSING	 0xC0220101
+#define STATUS_FWP_INJECT_HANDLE_STALE	 0xC0220102
+#define STATUS_FWP_CANNOT_PEND	 0xC0220103
+#define STATUS_NDIS_CLOSING	 0xC0230002
+#define STATUS_NDIS_BAD_VERSION	 0xC0230004
+#define STATUS_NDIS_BAD_CHARACTERISTICS	 0xC0230005
+#define STATUS_NDIS_ADAPTER_NOT_FOUND	 0xC0230006
+#define STATUS_NDIS_OPEN_FAILED	 0xC0230007
+#define STATUS_NDIS_DEVICE_FAILED	 0xC0230008
+#define STATUS_NDIS_MULTICAST_FULL	 0xC0230009
+#define STATUS_NDIS_MULTICAST_EXISTS	 0xC023000A
+#define STATUS_NDIS_MULTICAST_NOT_FOUND	 0xC023000B
+#define STATUS_NDIS_REQUEST_ABORTED	 0xC023000C
+#define STATUS_NDIS_RESET_IN_PROGRESS	 0xC023000D
+#define STATUS_NDIS_INVALID_PACKET	 0xC023000F
+#define STATUS_NDIS_INVALID_DEVICE_REQUEST	 0xC0230010
+#define STATUS_NDIS_ADAPTER_NOT_READY	 0xC0230011
+#define STATUS_NDIS_INVALID_LENGTH	 0xC0230014
+#define STATUS_NDIS_INVALID_DATA	 0xC0230015
+#define STATUS_NDIS_BUFFER_TOO_SHORT	 0xC0230016
+#define STATUS_NDIS_INVALID_OID	 0xC0230017
+#define STATUS_NDIS_ADAPTER_REMOVED	 0xC0230018
+#define STATUS_NDIS_UNSUPPORTED_MEDIA	 0xC0230019
+#define STATUS_NDIS_GROUP_ADDRESS_IN_USE	 0xC023001A
+#define STATUS_NDIS_FILE_NOT_FOUND	 0xC023001B
+#define STATUS_NDIS_ERROR_READING_FILE	 0xC023001C
+#define STATUS_NDIS_ALREADY_MAPPED	 0xC023001D
+#define STATUS_NDIS_RESOURCE_CONFLICT	 0xC023001E
+#define STATUS_NDIS_MEDIA_DISCONNECTED	 0xC023001F
+#define STATUS_NDIS_INVALID_ADDRESS	 0xC0230022
+#define STATUS_NDIS_PAUSED	 0xC023002A
+#define STATUS_NDIS_INTERFACE_NOT_FOUND	 0xC023002B
+#define STATUS_NDIS_UNSUPPORTED_REVISION	 0xC023002C
+#define STATUS_NDIS_INVALID_PORT	 0xC023002D
+#define STATUS_NDIS_INVALID_PORT_STATE	 0xC023002E
+#define STATUS_NDIS_LOW_POWER_STATE	 0xC023002F
+#define STATUS_NDIS_NOT_SUPPORTED	 0xC02300BB
+#define STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED	 0xC0232000
+#define STATUS_NDIS_DOT11_MEDIA_IN_USE	 0xC0232001
+#define STATUS_NDIS_DOT11_POWER_STATE_INVALID	 0xC0232002
+#define STATUS_IPSEC_BAD_SPI	 0xC0360001
+#define STATUS_IPSEC_SA_LIFETIME_EXPIRED	 0xC0360002
+#define STATUS_IPSEC_WRONG_SA	 0xC0360003
+#define STATUS_IPSEC_REPLAY_CHECK_FAILED	 0xC0360004
+#define STATUS_IPSEC_INVALID_PACKET	 0xC0360005
+#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED	 0xC0360006
+#define STATUS_IPSEC_CLEAR_TEXT_DROP	 0xC0360007
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/22] CIFS: Make transport routines work with SMB2
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2012-06-19 12:39   ` [PATCH 01/22] CIFS: Add SMB2 status codes Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
       [not found]     ` <1340109611-7210-4-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2012-06-19 12:39   ` [PATCH 04/22] CIFS: Add SMB2 credits support Pavel Shilovsky
                     ` (18 subsequent siblings)
  20 siblings, 1 reply; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/Makefile        |    2 +-
 fs/cifs/cifsglob.h      |    5 ++
 fs/cifs/cifsproto.h     |    3 +-
 fs/cifs/smb1ops.c       |    1 +
 fs/cifs/smb2ops.c       |   18 ++++++
 fs/cifs/smb2pdu.h       |   59 ++++++++++++++++++
 fs/cifs/smb2proto.h     |    5 ++
 fs/cifs/smb2transport.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/transport.c     |   13 ++--
 9 files changed, 248 insertions(+), 9 deletions(-)
 create mode 100644 fs/cifs/smb2transport.c

diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 4a77271..a73d7f8 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -16,4 +16,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
 
 cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
 
-cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o
+cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1266e2e..ae27ab8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -22,6 +22,7 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/slab.h>
+#include <linux/mempool.h>
 #include <linux/workqueue.h>
 #include "cifs_fs_sb.h"
 #include "cifsacl.h"
@@ -218,6 +219,7 @@ struct smb_version_values {
 	size_t		header_size;
 	size_t		max_header_size;
 	size_t		read_rsp_size;
+	__le16		lock_cmd;
 };
 
 #define HEADER_SIZE(server) (server->vals->header_size)
@@ -812,6 +814,7 @@ typedef void (mid_callback_t)(struct mid_q_entry *mid);
 /* one of these for every pending CIFS request to the server */
 struct mid_q_entry {
 	struct list_head qhead;	/* mids waiting on reply from this server */
+	struct TCP_Server_Info *server;	/* server corresponding to this mid */
 	__u64 mid;		/* multiplex id */
 	__u32 pid;		/* process id */
 	__u32 sequence_number;  /* for CIFS signing */
@@ -1153,6 +1156,8 @@ void cifs_oplock_break(struct work_struct *work);
 extern const struct slow_work_ops cifs_oplock_break_ops;
 extern struct workqueue_struct *cifsiod_wq;
 
+extern mempool_t *cifs_mid_poolp;
+
 /* Operations for different SMB versions */
 #define SMB1_VERSION_STRING	"1.0"
 extern struct smb_version_operations smb1_operations;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 2f4f661..c45adfa 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -36,7 +36,7 @@ extern void cifs_buf_release(void *);
 extern struct smb_hdr *cifs_small_buf_get(void);
 extern void cifs_small_buf_release(void *);
 extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
-			unsigned int /* length */);
+		    unsigned int /* length */);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
 #define GetXid()						\
@@ -68,6 +68,7 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
 extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
 					struct TCP_Server_Info *server);
 extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
+extern void cifs_wake_up_task(struct mid_q_entry *mid);
 extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
 			   unsigned int nvec, mid_receive_t *receive,
 			   mid_callback_t *callback, void *cbdata,
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 1a3f08c..cd7fbfd 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -445,4 +445,5 @@ struct smb_version_values smb1_values = {
 	.header_size = sizeof(struct smb_hdr),
 	.max_header_size = MAX_CIFS_HDR_SIZE,
 	.read_rsp_size = sizeof(READ_RSP),
+	.lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
 };
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index f065e89..80d9674 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -18,10 +18,28 @@
  */
 
 #include "cifsglob.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+
+static __u64
+smb2_get_next_mid(struct TCP_Server_Info *server)
+{
+	__u64 mid;
+	/* for SMB2 we need the current value */
+	spin_lock(&GlobalMid_Lock);
+	mid = server->CurrentMid;
+	server->CurrentMid++;
+	spin_unlock(&GlobalMid_Lock);
+	return mid;
+}
 
 struct smb_version_operations smb21_operations = {
+	.setup_request = smb2_setup_request,
+	.check_receive = smb2_check_receive,
+	.get_next_mid = smb2_get_next_mid,
 };
 
 struct smb_version_values smb21_values = {
 	.version_string = SMB21_VERSION_STRING,
+	.lock_cmd = SMB2_LOCK,
 };
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index d35ac68..ed73201 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -27,6 +27,65 @@
 #include <net/sock.h>
 
 /*
+ * Note that, due to trying to use names similar to the protocol specifications,
+ * there are many mixed case field names in the structures below.  Although
+ * this does not match typical Linux kernel style, it is necessary to be
+ * be able to match against the protocol specfication.
+ *
+ * SMB2 commands
+ * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
+ * (ie no useful data other than the SMB error code itself) and are marked such.
+ * Knowing this helps avoid response buffer allocations and copy in some cases.
+ */
+
+/* List of commands in host endian */
+#define SMB2NEGOTIATE		0x0000
+#define SMB2SESSION_SETUP	0x0001
+#define SMB2LOGOFF		0x0002 /* trivial request/resp */
+#define SMB2TREE_CONNECT	0x0003
+#define SMB2TREE_DISCONNECT	0x0004 /* trivial req/resp */
+#define SMB2CREATE		0x0005
+#define SMB2CLOSE		0x0006
+#define SMB2FLUSH		0x0007 /* trivial resp */
+#define SMB2READ		0x0008
+#define SMB2WRITE		0x0009
+#define SMB2LOCK		0x000A
+#define SMB2IOCTL		0x000B
+#define SMB2CANCEL		0x000C
+#define SMB2ECHO		0x000D
+#define SMB2QUERY_DIRECTORY	0x000E
+#define SMB2CHANGE_NOTIFY	0x000F
+#define SMB2QUERY_INFO		0x0010
+#define SMB2SET_INFO		0x0011
+#define SMB2OPLOCK_BREAK	0x0012
+
+/* The same list in little endian */
+#define SMB2_NEGOTIATE		cpu_to_le16(SMB2NEGOTIATE)
+#define SMB2_SESSION_SETUP	cpu_to_le16(SMB2SESSION_SETUP)
+#define SMB2_LOGOFF		cpu_to_le16(SMB2LOGOFF)
+#define SMB2_TREE_CONNECT	cpu_to_le16(SMB2TREE_CONNECT)
+#define SMB2_TREE_DISCONNECT	cpu_to_le16(SMB2TREE_DISCONNECT)
+#define SMB2_CREATE		cpu_to_le16(SMB2CREATE)
+#define SMB2_CLOSE		cpu_to_le16(SMB2CLOSE)
+#define SMB2_FLUSH		cpu_to_le16(SMB2FLUSH)
+#define SMB2_READ		cpu_to_le16(SMB2READ)
+#define SMB2_WRITE		cpu_to_le16(SMB2WRITE)
+#define SMB2_LOCK		cpu_to_le16(SMB2LOCK)
+#define SMB2_IOCTL		cpu_to_le16(SMB2IOCTL)
+#define SMB2_CANCEL		cpu_to_le16(SMB2CANCEL)
+#define SMB2_ECHO		cpu_to_le16(SMB2ECHO)
+#define SMB2_QUERY_DIRECTORY	cpu_to_le16(SMB2QUERY_DIRECTORY)
+#define SMB2_CHANGE_NOTIFY	cpu_to_le16(SMB2CHANGE_NOTIFY)
+#define SMB2_QUERY_INFO		cpu_to_le16(SMB2QUERY_INFO)
+#define SMB2_SET_INFO		cpu_to_le16(SMB2SET_INFO)
+#define SMB2_OPLOCK_BREAK	cpu_to_le16(SMB2OPLOCK_BREAK)
+
+#define NUMBER_OF_SMB2_COMMANDS	0x0013
+
+/* BB FIXME - analyze following length BB */
+#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
+
+/*
  * SMB2 Header Definition
  *
  * "MBZ" :  Must be Zero
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 08249ee..0e59afb 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -34,4 +34,9 @@ struct statfs;
  */
 extern int map_smb2_to_linux_error(char *buf, bool log_err);
 
+extern int smb2_check_receive(struct mid_q_entry *mid,
+			      struct TCP_Server_Info *server, bool log_error);
+extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
+			      unsigned int nvec, struct mid_q_entry **ret_mid);
+
 #endif			/* _SMB2PROTO_H */
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
new file mode 100644
index 0000000..74830f2
--- /dev/null
+++ b/fs/cifs/smb2transport.c
@@ -0,0 +1,151 @@
+/*
+ *   fs/cifs/smb2transport.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002, 2011
+ *                 Etersoft, 2012
+ *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
+ *              Jeremy Allison (jra-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2006
+ *              Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2012
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/net.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <asm/processor.h>
+#include <linux/mempool.h>
+#include "smb2pdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_debug.h"
+#include "smb2status.h"
+
+/*
+ * Set message id for the request. Should be called after wait_for_free_request
+ * and when srv_mutex is held. iov array must have at least 1 element.
+ */
+static inline void
+smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct kvec *iov)
+{
+	((struct smb2_hdr *)iov[0].iov_base)->MessageId = get_next_mid(server);
+}
+
+static struct mid_q_entry *
+smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
+		     struct TCP_Server_Info *server)
+{
+	struct mid_q_entry *temp;
+
+	if (server == NULL) {
+		cERROR(1, "Null TCP session in smb2_mid_entry_alloc");
+		return NULL;
+	}
+
+	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
+	if (temp == NULL)
+		return temp;
+	else {
+		memset(temp, 0, sizeof(struct mid_q_entry));
+		temp->mid = smb_buffer->MessageId;	/* always LE */
+		temp->pid = current->pid;
+		temp->command = smb_buffer->Command;	/* Always LE */
+		temp->when_alloc = jiffies;
+		temp->server = server;
+
+		/*
+		 * The default is for the mid to be synchronous, so the
+		 * default callback just wakes up the current task.
+		 */
+		temp->callback = cifs_wake_up_task;
+		temp->callback_data = current;
+	}
+
+	atomic_inc(&midCount);
+	temp->mid_state = MID_REQUEST_ALLOCATED;
+	return temp;
+}
+
+static int
+smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
+		   struct mid_q_entry **mid)
+{
+	if (ses->server->tcpStatus == CifsExiting)
+		return -ENOENT;
+
+	if (ses->server->tcpStatus == CifsNeedReconnect) {
+		cFYI(1, "tcp session dead - return to caller to retry");
+		return -EAGAIN;
+	}
+
+	if (ses->status != CifsGood) {
+		/* check if SMB2 session is bad because we are setting it up */
+		if ((buf->Command != SMB2_SESSION_SETUP) &&
+		    (buf->Command != SMB2_NEGOTIATE))
+			return -EAGAIN;
+		/* else ok - we are setting up session */
+	}
+	*mid = smb2_mid_entry_alloc(buf, ses->server);
+	if (*mid == NULL)
+		return -ENOMEM;
+	spin_lock(&GlobalMid_Lock);
+	list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
+	spin_unlock(&GlobalMid_Lock);
+	return 0;
+}
+
+int
+smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+		   bool log_error)
+{
+	unsigned int len = get_rfc1002_length(mid->resp_buf);
+
+	dump_smb(mid->resp_buf, min_t(u32, 80, len));
+	/* convert the length into a more usable form */
+	/* BB - uncomment with SMB2 signing implementation */
+	/* if ((len > 24) &&
+	    (server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) {
+		if (smb2_verify_signature(mid->resp_buf, server))
+			cERROR(1, "Unexpected SMB signature");
+	} */
+
+	return map_smb2_to_linux_error(mid->resp_buf, log_error);
+}
+
+int
+smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
+		   unsigned int nvec, struct mid_q_entry **ret_mid)
+{
+	int rc;
+	struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
+	struct mid_q_entry *mid;
+
+	smb2_seq_num_into_buf(ses->server, iov);
+
+	rc = smb2_get_mid_entry(ses, hdr, &mid);
+	if (rc)
+		return rc;
+	/* rc = smb2_sign_smb2(iov, nvec, ses->server);
+	if (rc)
+		delete_mid(mid); */
+	*ret_mid = mid;
+	return rc;
+}
+
+/* BB add missing functions here */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 54cd8dd..ea86753 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -35,10 +35,8 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 
-extern mempool_t *cifs_mid_poolp;
-
-static void
-wake_up_task(struct mid_q_entry *mid)
+void
+cifs_wake_up_task(struct mid_q_entry *mid)
 {
 	wake_up_process(mid->callback_data);
 }
@@ -65,12 +63,13 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
 	/*	do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
 		/* when mid allocated can be before when sent */
 		temp->when_alloc = jiffies;
+		temp->server = server;
 
 		/*
 		 * The default is for the mid to be synchronous, so the
 		 * default callback just wakes up the current task.
 		 */
-		temp->callback = wake_up_task;
+		temp->callback = cifs_wake_up_task;
 		temp->callback_data = current;
 	}
 
@@ -83,6 +82,7 @@ void
 DeleteMidQEntry(struct mid_q_entry *midEntry)
 {
 #ifdef CONFIG_CIFS_STATS2
+	__le16 command = midEntry->server->vals->lock_cmd;
 	unsigned long now;
 #endif
 	midEntry->mid_state = MID_FREE;
@@ -96,8 +96,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
 	/* commands taking longer than one second are indications that
 	   something is wrong, unless it is quite a slow link or server */
 	if ((now - midEntry->when_alloc) > HZ) {
-		if ((cifsFYI & CIFS_TIMER) &&
-		    (midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) {
+		if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
 			printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
 			       midEntry->command, midEntry->mid);
 			printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/22] CIFS: Add SMB2 credits support
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
  2012-06-19 12:39   ` [PATCH 01/22] CIFS: Add SMB2 status codes Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 03/22] CIFS: Make transport routines work with SMB2 Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 05/22] CIFS: Make demultiplex_thread work with SMB2 code Pavel Shilovsky
                     ` (17 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

For SMB2 protocol we can add more than one credit for one received
request: it depends on CreditRequest field in SMB2 response header.
Also we divide all requests by type: echos, oplocks and others. Each
type uses its own slot pull.

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h  |    5 +++
 fs/cifs/cifsproto.h |    1 +
 fs/cifs/connect.c   |    2 +-
 fs/cifs/smb2ops.c   |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 84 insertions(+), 1 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ae27ab8..6c062e2 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -343,6 +343,11 @@ struct TCP_Server_Info {
 	char server_GUID[16];
 	__u16 sec_mode;
 	bool session_estab; /* mark when very first sess is established */
+#ifdef CONFIG_CIFS_SMB2
+	int echo_credits;  /* echo reserved slots */
+	int oplock_credits;  /* oplock break reserved slots */
+	bool echos:1; /* enable echos */
+#endif
 	u16 dialect; /* dialect index that server chose */
 	enum securityEnum secType;
 	bool oplocks:1; /* enable oplocks */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c45adfa..19987a7 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -91,6 +91,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
 			struct smb_hdr *in_buf ,
 			struct smb_hdr *out_buf,
 			int *bytes_returned);
+extern int cifs_reconnect(struct TCP_Server_Info *server);
 extern int checkSMB(char *buf, unsigned int length);
 extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
 extern bool backup_cred(struct cifs_sb_info *);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 72fb35b..d45df03 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -296,7 +296,7 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
  * reconnect tcp session
  * wake up waiters on reconnection? - (not needed currently)
  */
-static int
+int
 cifs_reconnect(struct TCP_Server_Info *server)
 {
 	int rc = 0;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 80d9674..1393d70 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -20,6 +20,79 @@
 #include "cifsglob.h"
 #include "smb2pdu.h"
 #include "smb2proto.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+static void
+change_conf(struct TCP_Server_Info *server)
+{
+	server->credits += server->echo_credits + server->oplock_credits;
+	server->oplock_credits = server->echo_credits = 0;
+	switch (server->credits) {
+	case 0:
+		cifs_reconnect(server);
+		return;
+	case 1:
+		server->echos = false;
+		server->oplocks = false;
+		cERROR(1, "disabling echos and oplocks");
+		break;
+	case 2:
+		server->echos = true;
+		server->oplocks = false;
+		server->echo_credits = 1;
+		cFYI(1, "disabling oplocks");
+		break;
+	default:
+		server->echos = true;
+		server->oplocks = true;
+		server->echo_credits = 1;
+		server->oplock_credits = 1;
+	}
+	server->credits -= server->echo_credits + server->oplock_credits;
+}
+
+static void
+smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
+		 const int optype)
+{
+	int *val;
+	spin_lock(&server->req_lock);
+	val = server->ops->get_credits_field(server, optype);
+	*val += add;
+	server->in_flight--;
+	if (server->in_flight == 0)
+		change_conf(server);
+	spin_unlock(&server->req_lock);
+	wake_up(&server->request_q);
+}
+
+static void
+smb2_set_credits(struct TCP_Server_Info *server, const int val)
+{
+	spin_lock(&server->req_lock);
+	server->credits = val;
+	spin_unlock(&server->req_lock);
+}
+
+static int *
+smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
+{
+	switch (optype) {
+	case CIFS_ECHO_OP:
+		return &server->echo_credits;
+	case CIFS_OBREAK_OP:
+		return &server->oplock_credits;
+	default:
+		return &server->credits;
+	}
+}
+
+static unsigned int
+smb2_get_credits(struct mid_q_entry *mid)
+{
+	return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
+}
 
 static __u64
 smb2_get_next_mid(struct TCP_Server_Info *server)
@@ -36,6 +109,10 @@ smb2_get_next_mid(struct TCP_Server_Info *server)
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
+	.add_credits = smb2_add_credits,
+	.set_credits = smb2_set_credits,
+	.get_credits_field = smb2_get_credits_field,
+	.get_credits = smb2_get_credits,
 	.get_next_mid = smb2_get_next_mid,
 };
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/22] CIFS: Make demultiplex_thread work with SMB2 code
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (2 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 04/22] CIFS: Add SMB2 credits support Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 06/22] CIFS: Respect SMB2 header/max header size Pavel Shilovsky
                     ` (16 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Now we can process SMB2 messages: check message, get message id
and wakeup awaiting routines.

Signed-off-by: Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/cifs/Makefile     |    2 +-
 fs/cifs/cifs_debug.c |    2 +-
 fs/cifs/smb2misc.c   |  304 ++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2ops.c    |   37 ++++++
 fs/cifs/smb2pdu.h    |   30 +++++
 fs/cifs/smb2proto.h  |    2 +
 6 files changed, 375 insertions(+), 2 deletions(-)
 create mode 100644 fs/cifs/smb2misc.c

diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index a73d7f8..b77e9ec 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -16,4 +16,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
 
 cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
 
-cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o
+cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o smb2misc.o
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index e814052..8aa8693 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -65,7 +65,7 @@ void cifs_dump_detail(void *buf)
 	cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
 		  smb->Command, smb->Status.CifsError,
 		  smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
-	cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb));
+	cERROR(1, "smb buf %p len %u", smb, smbCalcSize(smb));
 #endif /* CONFIG_CIFS_DEBUG2 */
 }
 
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
new file mode 100644
index 0000000..03167eb
--- /dev/null
+++ b/fs/cifs/smb2misc.c
@@ -0,0 +1,304 @@
+/*
+ *   fs/cifs/smb2misc.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2011
+ *                 Etersoft, 2012
+ *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
+ *              Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2012
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/ctype.h>
+#include "smb2pdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_debug.h"
+#include "cifs_unicode.h"
+#include "smb2status.h"
+
+static int
+check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
+{
+	/*
+	 * Make sure that this really is an SMB, that it is a response,
+	 * and that the message ids match
+	 */
+	if ((*(__le32 *)hdr->ProtocolId == cpu_to_le32(0x424d53fe)) &&
+	    (mid == hdr->MessageId)) {
+		if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
+			return 0;
+		else {
+			/* only one valid case where server sends us request */
+			if (hdr->Command == SMB2_OPLOCK_BREAK)
+				return 0;
+			else
+				cERROR(1, "Received Request not response");
+		}
+	} else { /* bad signature or mid */
+		if (*(__le32 *)hdr->ProtocolId != cpu_to_le32(0x424d53fe))
+			cERROR(1, "Bad protocol string signature header %x",
+			       *(unsigned int *) hdr->ProtocolId);
+		if (mid != hdr->MessageId)
+			cERROR(1, "Mids do not match");
+	}
+	cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId);
+	return 1;
+}
+
+/*
+ *  The following table defines the expected "StructureSize" of SMB2 responses
+ *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS responses.
+ *
+ *  Note that commands are defined in smb2pdu.h in le16 but the array below is
+ *  indexed by command in host byte order
+ */
+static const int smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
+	/* SMB2_NEGOTIATE */ 65,
+	/* SMB2_SESSION_SETUP */ 9,
+	/* SMB2_LOGOFF */ 4,
+	/* SMB2_TREE_CONNECT */	16,
+	/* SMB2_TREE_DISCONNECT */ 4,
+	/* SMB2_CREATE */ 89,
+	/* SMB2_CLOSE */ 60,
+	/* SMB2_FLUSH */ 4,
+	/* SMB2_READ */	17,
+	/* SMB2_WRITE */ 17,
+	/* SMB2_LOCK */	4,
+	/* SMB2_IOCTL */ 49,
+	/* SMB2_CANCEL */ 0, /* BB CHECK this ... not listed in documentation */
+	/* SMB2_ECHO */ 4,
+	/* SMB2_QUERY_DIRECTORY */ 9,
+	/* SMB2_CHANGE_NOTIFY */ 9,
+	/* SMB2_QUERY_INFO */ 9,
+	/* SMB2_SET_INFO */ 2,
+	/* SMB2_OPLOCK_BREAK */ 24 /* BB FIXME can also be 44 for lease break */
+};
+
+int
+smb2_check_message(char *buf, unsigned int length)
+{
+	struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
+	struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
+	__u64 mid = hdr->MessageId;
+	__u32 len = get_rfc1002_length(buf);
+	__u32 clc_len;  /* calculated length */
+	int command;
+
+	/* BB disable following printk later */
+	cFYI(1, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len);
+
+	/*
+	 * Add function to do table lookup of StructureSize by command
+	 * ie Validate the wct via smb2_struct_sizes table above
+	 */
+
+	if (length < 2 + sizeof(struct smb2_hdr)) {
+		if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) {
+			pdu->StructureSize2 = 0;
+			/*
+			 * As with SMB/CIFS, on some error cases servers may
+			 * not return wct properly
+			 */
+			return 0;
+		} else {
+			cERROR(1, "Length less than smb header size");
+		}
+		return 1;
+	}
+	if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
+		cERROR(1, "smb length greater than maximum, mid=%lld", mid);
+		return 1;
+	}
+
+	if (check_smb2_hdr(hdr, mid))
+		return 1;
+
+	if (le16_to_cpu(hdr->StructureSize) != 64) {
+		cERROR(1, "Illegal structure size %d",
+			  le16_to_cpu(hdr->StructureSize));
+		return 1;
+	}
+
+	command = le16_to_cpu(hdr->Command);
+	if (command >= NUMBER_OF_SMB2_COMMANDS) {
+		cERROR(1, "illegal SMB2 command %d", command);
+		return 1;
+	}
+
+	if (smb2_rsp_struct_sizes[command] !=
+	    le16_to_cpu(pdu->StructureSize2)) {
+		if ((hdr->Status == 0) ||
+		    (le16_to_cpu(pdu->StructureSize2) != 9)) {
+			/* error packets have 9 byte structure size */
+			cERROR(1, "Illegal response size %d for command %d",
+				   le16_to_cpu(pdu->StructureSize2), command);
+			return 1;
+		}
+	}
+
+	clc_len = smb2_calc_size(hdr);
+
+	if (4 + len != length) {
+		cERROR(1, "Length read does not match RFC1001 length %d",
+			   len);
+		return 1;
+	}
+
+	if (4 + len != clc_len) {
+		cFYI(1, "Calculated size %d length %d mismatch for mid %lld",
+			 clc_len, 4 + len, mid);
+		if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */
+			return 0; /* BB workaround Samba 3 bug SessSetup rsp */
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ *  The size of the variable area depends on the offset and length fields
+ *  located in different fields for various SMB2 responses.  SMB2 responses
+ *  with no variable length info, show an offset of zero for the offset field.
+ */
+static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
+	/* SMB2_NEGOTIATE */ true,
+	/* SMB2_SESSION_SETUP */ true,
+	/* SMB2_LOGOFF */ false,
+	/* SMB2_TREE_CONNECT */	false,
+	/* SMB2_TREE_DISCONNECT */ false,
+	/* SMB2_CREATE */ true,
+	/* SMB2_CLOSE */ false,
+	/* SMB2_FLUSH */ false,
+	/* SMB2_READ */	true,
+	/* SMB2_WRITE */ false,
+	/* SMB2_LOCK */	false,
+	/* SMB2_IOCTL */ true,
+	/* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
+	/* SMB2_ECHO */ false,
+	/* SMB2_QUERY_DIRECTORY */ true,
+	/* SMB2_CHANGE_NOTIFY */ true,
+	/* SMB2_QUERY_INFO */ true,
+	/* SMB2_SET_INFO */ false,
+	/* SMB2_OPLOCK_BREAK */ false
+};
+
+/*
+ * Returns the pointer to the beginning of the data area. Length of the data
+ * area and the offset to it (from the beginning of the smb are also returned.
+ */
+static char *
+smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
+{
+	*off = 0;
+	*len = 0;
+
+	/* error responses do not have data area */
+	if (hdr->Status &&
+	   (le32_to_cpu(hdr->Status) != STATUS_MORE_PROCESSING_REQUIRED) &&
+	   (le16_to_cpu(((struct smb2_err_rsp *)hdr)->StructureSize) == 9))
+		return NULL;
+
+	/*
+	 * Following commands have data areas so we have to get the location
+	 * of the data buffer offset and data buffer length for the particular
+	 * command.
+	 */
+	switch (hdr->Command) {
+	case SMB2_NEGOTIATE:
+	case SMB2_SESSION_SETUP:
+	case SMB2_CREATE:
+	case SMB2_READ:
+	case SMB2_QUERY_INFO:
+	case SMB2_QUERY_DIRECTORY:
+	case SMB2_IOCTL:
+	case SMB2_CHANGE_NOTIFY:
+	default:
+		/* BB FIXME for unimplemented cases above */
+		cERROR(1, "no length check for command");
+		break;
+	}
+
+	/*
+	 * Invalid length or offset probably means data area is invalid, but
+	 * we have little choice but to ignore the data area in this case.
+	 */
+	if (*off > 4096) {
+		dump_stack();
+		cERROR(1, "offset %d too large, data area ignored", *off);
+		*len = 0;
+		*off = 0;
+	} else if (*off < 0) {
+		cERROR(1, "negative offset to data invalid ignore data area");
+		*off = 0;
+		*len = 0;
+	} else if (*len < 0) {
+		cERROR(1, "negative data length invalid, data area ignored");
+		*len = 0;
+	} else if (*len > 128 * 1024) {
+		cERROR(1, "data area larger than 128K");
+		*len = 0;
+	}
+
+	/* return pointer to beginning of data area, ie offset from SMB start */
+	if ((*off != 0) && (*len != 0))
+		return hdr->ProtocolId + *off;
+	else
+		return NULL;
+}
+
+/*
+ * Calculate the size of the SMB message based on the fixed header
+ * portion, the number of word parameters and the data portion of the message.
+ */
+unsigned int
+smb2_calc_size(struct smb2_hdr *hdr)
+{
+	struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
+	int offset; /* the offset from the beginning of SMB to data area */
+	int data_length; /* the length of the variable length data area */
+	/* Structure Size has already been checked to make sure it is 64 */
+	int len = 4 + le16_to_cpu(pdu->hdr.StructureSize);
+
+	/*
+	 * StructureSize2, ie length of fixed parameter area has already
+	 * been checked to make sure it is the correct length.
+	 */
+	len += le16_to_cpu(pdu->StructureSize2);
+
+	if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
+		goto calc_size_exit;
+
+	smb2_get_data_area_len(&offset, &data_length, hdr);
+	cFYI(1, "smb2 data length %d offset %d", data_length, offset);
+
+	if (data_length > 0) {
+		/*
+		 * Check to make sure that data area begins after fixed area,
+		 * Note that last byte of the fixed area is part of data area
+		 * for some commands, typically those with odd StructureSize,
+		 * so we must add one to the calculation (and 4 to account for
+		 * the size of the RFC1001 hdr.
+		 */
+		if (offset + 4 + 1 < len) {
+			cERROR(1, "data area overlaps SMB2 header, ignoring");
+			data_length = 0;
+		} else {
+			len = 4 + offset + data_length;
+		}
+	}
+calc_size_exit:
+	cFYI(1, "smb2 len %d", len);
+	return len;
+}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 1393d70..696525f 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -106,6 +106,38 @@ smb2_get_next_mid(struct TCP_Server_Info *server)
 	return mid;
 }
 
+static struct mid_q_entry *
+smb2_find_mid(struct TCP_Server_Info *server, char *buf)
+{
+	struct mid_q_entry *mid;
+	struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
+
+	spin_lock(&GlobalMid_Lock);
+	list_for_each_entry(mid, &server->pending_mid_q, qhead) {
+		if ((mid->mid == hdr->MessageId) &&
+		    (mid->mid_state == MID_REQUEST_SUBMITTED) &&
+		    (mid->command == hdr->Command)) {
+			spin_unlock(&GlobalMid_Lock);
+			return mid;
+		}
+	}
+	spin_unlock(&GlobalMid_Lock);
+	return NULL;
+}
+
+static void
+smb2_dump_detail(void *buf)
+{
+#ifdef CONFIG_CIFS_DEBUG2
+	struct smb2_hdr *smb = (struct smb2_hdr *)buf;
+
+	cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d",
+		  smb->Command, smb->Status, smb->Flags, smb->MessageId,
+		  smb->ProcessId);
+	cERROR(1, "smb buf %p len %u", smb, smb2_calc_size(smb));
+#endif
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -114,9 +146,14 @@ struct smb_version_operations smb21_operations = {
 	.get_credits_field = smb2_get_credits_field,
 	.get_credits = smb2_get_credits,
 	.get_next_mid = smb2_get_next_mid,
+	.find_mid = smb2_find_mid,
+	.check_message = smb2_check_message,
+	.dump_detail = smb2_dump_detail,
 };
 
 struct smb_version_values smb21_values = {
 	.version_string = SMB21_VERSION_STRING,
+	.header_size = sizeof(struct smb2_hdr),
+	.max_header_size = MAX_SMB2_HDR_SIZE,
 	.lock_cmd = SMB2_LOCK,
 };
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index ed73201..0a17588 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -112,4 +112,34 @@ struct smb2_hdr {
 	__u8   Signature[16];
 } __packed;
 
+struct smb2_pdu {
+	struct smb2_hdr hdr;
+	__le16 StructureSize2; /* size of wct area (varies, request specific) */
+} __packed;
+
+/*
+ *	SMB2 flag definitions
+ */
+#define SMB2_FLAGS_SERVER_TO_REDIR	cpu_to_le32(0x00000001) /* Response */
+#define SMB2_FLAGS_ASYNC_COMMAND	cpu_to_le32(0x00000002)
+#define SMB2_FLAGS_RELATED_OPERATIONS	cpu_to_le32(0x00000004)
+#define SMB2_FLAGS_SIGNED		cpu_to_le32(0x00000008)
+#define SMB2_FLAGS_DFS_OPERATIONS	cpu_to_le32(0x10000000)
+
+/*
+ *	Definitions for SMB2 Protocol Data Units (network frames)
+ *
+ *  See MS-SMB2.PDF specification for protocol details.
+ *  The Naming convention is the lower case version of the SMB2
+ *  command code name for the struct. Note that structures must be packed.
+ *
+ */
+struct smb2_err_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;
+	__le16 Reserved; /* MBZ */
+	__le32 ByteCount;  /* even if zero, at least one byte follows */
+	__u8   ErrorData[1];  /* variable length */
+} __packed;
+
 #endif				/* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 0e59afb..19bf987 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -33,6 +33,8 @@ struct statfs;
  *****************************************************************
  */
 extern int map_smb2_to_linux_error(char *buf, bool log_err);
+extern int smb2_check_message(char *buf, unsigned int length);
+extern unsigned int smb2_calc_size(struct smb2_hdr *hdr);
 
 extern int smb2_check_receive(struct mid_q_entry *mid,
 			      struct TCP_Server_Info *server, bool log_error);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/22] CIFS: Respect SMB2 header/max header size
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (3 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 05/22] CIFS: Make demultiplex_thread work with SMB2 code Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 07/22] CIFS: Add capability to send SMB2 negotiate message Pavel Shilovsky
                     ` (15 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Use SMB2 header size values for allocation and memset because they
are bigger and suitable for both CIFS and SMB2.

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/cifsfs.c |   14 ++++++++++++--
 fs/cifs/misc.c   |   25 +++++++++++++++++++------
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8b6e344..bb4b919 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -48,6 +48,9 @@
 #include <linux/key-type.h>
 #include "cifs_spnego.h"
 #include "fscache.h"
+#ifdef CONFIG_CIFS_SMB2
+#include "smb2pdu.h"
+#endif
 #define CIFS_MAGIC_NUMBER 0xFF534D42	/* the first four bytes of SMB PDUs */
 
 int cifsFYI = 0;
@@ -981,6 +984,14 @@ cifs_destroy_inodecache(void)
 static int
 cifs_init_request_bufs(void)
 {
+	size_t max_hdr_size = MAX_CIFS_HDR_SIZE;
+#ifdef CONFIG_CIFS_SMB2
+	/*
+	 * SMB2 maximum header size is bigger than CIFS one - no problems to
+	 * allocate some more bytes for CIFS.
+	 */
+	max_hdr_size = MAX_SMB2_HDR_SIZE;
+#endif
 	if (CIFSMaxBufSize < 8192) {
 	/* Buffer size can not be smaller than 2 * PATH_MAX since maximum
 	Unicode path name has to fit in any SMB/CIFS path based frames */
@@ -992,8 +1003,7 @@ cifs_init_request_bufs(void)
 	}
 /*	cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
 	cifs_req_cachep = kmem_cache_create("cifs_request",
-					    CIFSMaxBufSize +
-					    MAX_CIFS_HDR_SIZE, 0,
+					    CIFSMaxBufSize + max_hdr_size, 0,
 					    SLAB_HWCACHE_ALIGN, NULL);
 	if (cifs_req_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 557506a..df9f886 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -29,6 +29,9 @@
 #include "smberr.h"
 #include "nterr.h"
 #include "cifs_unicode.h"
+#ifdef CONFIG_CIFS_SMB2
+#include "smb2pdu.h"
+#endif
 
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
@@ -143,17 +146,27 @@ struct smb_hdr *
 cifs_buf_get(void)
 {
 	struct smb_hdr *ret_buf = NULL;
-
-/* We could use negotiated size instead of max_msgsize -
-   but it may be more efficient to always alloc same size
-   albeit slightly larger than necessary and maxbuffersize
-   defaults to this and can not be bigger */
+	size_t buf_size = sizeof(struct smb_hdr);
+
+#ifdef CONFIG_CIFS_SMB2
+	/*
+	 * SMB2 header is bigger than CIFS one - no problems to clean some
+	 * more bytes for CIFS.
+	 */
+	buf_size = sizeof(struct smb2_hdr);
+#endif
+	/*
+	 * We could use negotiated size instead of max_msgsize -
+	 * but it may be more efficient to always alloc same size
+	 * albeit slightly larger than necessary and maxbuffersize
+	 * defaults to this and can not be bigger.
+	 */
 	ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
 
 	/* clear the first few header bytes */
 	/* for most paths, more is cleared in header_assemble */
 	if (ret_buf) {
-		memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
+		memset(ret_buf, 0, buf_size + 3);
 		atomic_inc(&bufAllocCount);
 #ifdef CONFIG_CIFS_STATS2
 		atomic_inc(&totBufAllocCount);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/22] CIFS: Add capability to send SMB2 negotiate message
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (4 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 06/22] CIFS: Respect SMB2 header/max header size Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 08/22] CIFS: Add session setup/logoff capability for SMB2 Pavel Shilovsky
                     ` (14 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

and add negotiate request type to let set_credits know that
we are only on negotiate stage and no need to make a decision
about disabling echos and oplocks.

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/Makefile    |    3 +-
 fs/cifs/cifsglob.h  |    7 +-
 fs/cifs/smb2misc.c  |    7 +-
 fs/cifs/smb2ops.c   |   22 ++++-
 fs/cifs/smb2pdu.c   |  333 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.h   |   39 ++++++
 fs/cifs/smb2proto.h |    7 +
 7 files changed, 414 insertions(+), 4 deletions(-)
 create mode 100644 fs/cifs/smb2pdu.c

diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index b77e9ec..daf6837 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -16,4 +16,5 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
 
 cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
 
-cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o smb2misc.o
+cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o \
+			    smb2misc.o smb2pdu.o
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6c062e2..119c501 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -393,6 +393,10 @@ struct TCP_Server_Info {
 	atomic_t in_send; /* requests trying to send */
 	atomic_t num_waiters;   /* blocked waiting to get in sendrecv */
 #endif
+#ifdef CONFIG_CIFS_SMB2
+	unsigned int	max_read;
+	unsigned int	max_write;
+#endif /* CONFIG_CIFS_SMB2 */
 };
 
 static inline unsigned int
@@ -986,7 +990,8 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
 /* Type of request operation */
 #define   CIFS_ECHO_OP      0x080    /* echo request */
 #define   CIFS_OBREAK_OP   0x0100    /* oplock break request */
-#define   CIFS_OP_MASK     0x0180    /* mask request type */
+#define   CIFS_NEG_OP      0x0200    /* negotiate request */
+#define   CIFS_OP_MASK     0x0380    /* mask request type */
 
 /* Security Flags: indicate type of session setup needed */
 #define   CIFSSEC_MAY_SIGN	0x00001
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 03167eb..1cea426 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -198,7 +198,7 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
  * Returns the pointer to the beginning of the data area. Length of the data
  * area and the offset to it (from the beginning of the smb are also returned.
  */
-static char *
+char *
 smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 {
 	*off = 0;
@@ -217,6 +217,11 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 	 */
 	switch (hdr->Command) {
 	case SMB2_NEGOTIATE:
+		*off = le16_to_cpu(
+		    ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
+		*len = le16_to_cpu(
+		    ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
+		break;
 	case SMB2_SESSION_SETUP:
 	case SMB2_CREATE:
 	case SMB2_READ:
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 696525f..b980d18 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -61,7 +61,7 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
 	val = server->ops->get_credits_field(server, optype);
 	*val += add;
 	server->in_flight--;
-	if (server->in_flight == 0)
+	if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
 		change_conf(server);
 	spin_unlock(&server->req_lock);
 	wake_up(&server->request_q);
@@ -138,6 +138,24 @@ smb2_dump_detail(void *buf)
 #endif
 }
 
+static bool
+smb2_need_neg(struct TCP_Server_Info *server)
+{
+	return server->max_read == 0;
+}
+
+static int
+smb2_negotiate(const int xid, struct cifs_ses *ses)
+{
+	int rc;
+	ses->server->CurrentMid = 0;
+	rc = SMB2_negotiate(xid, ses);
+	/* BB we probably don't need to retry with modern servers */
+	if (rc == -EAGAIN)
+		rc = -EHOSTDOWN;
+	return rc;
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -149,6 +167,8 @@ struct smb_version_operations smb21_operations = {
 	.find_mid = smb2_find_mid,
 	.check_message = smb2_check_message,
 	.dump_detail = smb2_dump_detail,
+	.need_neg = smb2_need_neg,
+	.negotiate = smb2_negotiate,
 };
 
 struct smb_version_values smb21_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
new file mode 100644
index 0000000..21e291a
--- /dev/null
+++ b/fs/cifs/smb2pdu.c
@@ -0,0 +1,333 @@
+/*
+ *   fs/cifs/smb2pdu.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2009, 2011
+ *                 Etersoft, 2012
+ *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
+ *              Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2012
+ *
+ *   Contains the routines for constructing the SMB2 PDUs themselves
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
+ /* Note that there are handle based routines which must be		      */
+ /* treated slightly differently for reconnection purposes since we never     */
+ /* want to reuse a stale file handle and only the caller knows the file info */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vfs.h>
+#include <linux/uaccess.h>
+#include <linux/xattr.h>
+#include "smb2pdu.h"
+#include "cifsglob.h"
+#include "cifsacl.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "smb2status.h"
+
+/*
+ *  The following table defines the expected "StructureSize" of SMB2 requests
+ *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
+ *
+ *  Note that commands are defined in smb2pdu.h in le16 but the array below is
+ *  indexed by command in host byte order
+ */
+static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
+	/* SMB2_NEGOTIATE */ 36,
+	/* SMB2_SESSION_SETUP */ 25,
+	/* SMB2_LOGOFF */ 4,
+	/* SMB2_TREE_CONNECT */	9,
+	/* SMB2_TREE_DISCONNECT */ 4,
+	/* SMB2_CREATE */ 57,
+	/* SMB2_CLOSE */ 24,
+	/* SMB2_FLUSH */ 24,
+	/* SMB2_READ */	49,
+	/* SMB2_WRITE */ 49,
+	/* SMB2_LOCK */	48,
+	/* SMB2_IOCTL */ 57,
+	/* SMB2_CANCEL */ 4,
+	/* SMB2_ECHO */ 4,
+	/* SMB2_QUERY_DIRECTORY */ 33,
+	/* SMB2_CHANGE_NOTIFY */ 32,
+	/* SMB2_QUERY_INFO */ 41,
+	/* SMB2_SET_INFO */ 33,
+	/* SMB2_OPLOCK_BREAK */  24 /* BB this is 36 for LEASE_BREAK variant */
+};
+
+
+/*
+ * NB: MID can not be set if tcon not passed in, in that
+ * case it is responsbility of caller to set the mid
+ */
+static void
+smb2_hdr_assemble(struct smb2_hdr *buffer, __le16 smb2_cmd /* command */ ,
+		  const struct cifs_tcon *tcon)
+{
+	struct smb2_pdu *smb = (struct smb2_pdu *)buffer;
+	char *temp = (char *) buffer;
+	/* lookup word count ie StructureSize from table */
+	__u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_cmd)];
+
+	/*
+	 * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
+	 * largest operations (Create)
+	 */
+	memset(temp, 0, 256);
+
+	/* Note this is only network field converted to big endian */
+	buffer->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr)
+			- 4 /*  RFC 1001 length field itself not counted */);
+
+	buffer->ProtocolId[0] = 0xFE;
+	buffer->ProtocolId[1] = 'S';
+	buffer->ProtocolId[2] = 'M';
+	buffer->ProtocolId[3] = 'B';
+	buffer->StructureSize = cpu_to_le16(64);
+	buffer->Command = smb2_cmd;
+	buffer->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */
+	buffer->ProcessId = cpu_to_le32((__u16)current->tgid);
+
+	if (!tcon)
+		goto out;
+
+	buffer->TreeId = tcon->tid;
+	/* Uid is not converted */
+	if (tcon->ses)
+		buffer->SessionId = tcon->ses->Suid;
+	/* BB check following DFS flags BB */
+	/* BB do we have to add check for SHI1005_FLAGS_DFS_ROOT too? */
+	/* if (tcon->share_flags & SHI1005_FLAGS_DFS)
+		buffer->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
+	/* BB how does SMB2 do case sensitive? */
+	/* if (tcon->nocase)
+		buffer->Flags |= SMBFLG_CASELESS; */
+	/* if (tcon->ses && tcon->ses->server &&
+	    (tcon->ses->server->sec_mode & SECMODE_SIGN_REQUIRED))
+		buffer->Flags |= SMB2_FLAGS_SIGNED; */
+out:
+	smb->StructureSize2 = cpu_to_le16(parmsize);
+	return;
+}
+
+static int
+smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
+{
+	int rc = 0;
+	/* BB add missing code here */
+	return rc;
+}
+
+/*
+ * Allocate and return pointer to an SMB request buffer, and set basic
+ * SMB information in the SMB header. If the return code is zero, this
+ * function must have filled in request_buf pointer.
+ */
+static int
+small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
+		void **request_buf)
+{
+	int rc = 0;
+
+	rc = smb2_reconnect(smb2_command, tcon);
+	if (rc)
+		return rc;
+
+	/* BB eventually switch this to SMB2 specific small buf size */
+	*request_buf = cifs_small_buf_get();
+	if (*request_buf == NULL) {
+		/* BB should we add a retry in here if not a writepage? */
+		return -ENOMEM;
+	}
+
+	smb2_hdr_assemble((struct smb2_hdr *) *request_buf, smb2_command, tcon);
+
+	if (tcon != NULL) {
+#ifdef CONFIG_CIFS_STATS2
+		/*
+		uint16_t com_code = le16_to_cpu(smb2_command);
+		cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
+		*/
+#endif
+		cifs_stats_inc(&tcon->num_smbs_sent);
+	}
+
+	return rc;
+}
+
+static void free_rsp_buf(int resp_buftype, void *pSMB2r)
+{
+	if (resp_buftype == CIFS_SMALL_BUFFER)
+		cifs_small_buf_release(pSMB2r);
+	else if (resp_buftype == CIFS_LARGE_BUFFER)
+		cifs_buf_release(pSMB2r);
+}
+
+#define SMB2_NUM_PROT 1
+
+#define SMB2_PROT   0
+#define SMB21_PROT  1
+#define BAD_PROT 0xFFFF
+
+#define SMB2_PROT_ID  0x0202
+#define SMB21_PROT_ID 0x0210
+#define BAD_PROT_ID   0xFFFF
+
+static struct {
+	int index;
+	__le16 name;
+} smb2protocols[] = {
+	{SMB2_PROT,  cpu_to_le16(SMB2_PROT_ID)},
+	{SMB21_PROT, cpu_to_le16(SMB21_PROT_ID)},
+	{BAD_PROT,   cpu_to_le16(BAD_PROT_ID)}
+};
+
+/*
+ *
+ *	SMB2 Worker functions follow:
+ *
+ *	The general structure of the worker functions is:
+ *	1) Call smb2_init (assembles SMB2 header)
+ *	2) Initialize SMB2 command specific fields in fixed length area of SMB
+ *	3) Call smb_sendrcv2 (sends request on socket and waits for response)
+ *	4) Decode SMB2 command specific fields in the fixed length area
+ *	5) Decode variable length data area (if any for this SMB2 command type)
+ *	6) Call free smb buffer
+ *	7) return
+ *
+ */
+
+int
+SMB2_negotiate(const int xid, struct cifs_ses *ses)
+{
+	struct smb2_negotiate_req *pSMB2;
+	struct smb2_negotiate_rsp *pSMB2r;
+	struct kvec iov[1];
+	int rc = 0;
+	int resp_buftype;
+	struct TCP_Server_Info *server;
+	unsigned int sec_flags;
+	u16 i;
+	u16 temp = 0;
+	int blob_offset, blob_length;
+	char *security_blob;
+	int flags = CIFS_NEG_OP;
+
+	cFYI(1, "Negotiate protocol");
+
+	if (ses->server)
+		server = ses->server;
+	else {
+		rc = -EIO;
+		return rc;
+	}
+
+	rc = small_smb2_init(SMB2_NEGOTIATE, NULL, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	/* if any of auth flags (ie not sign or seal) are overriden use them */
+	if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
+		sec_flags = ses->overrideSecFlg;  /* BB FIXME fix sign flags?*/
+	else /* if override flags set only sign/seal OR them with global auth */
+		sec_flags = global_secflags | ses->overrideSecFlg;
+
+	cFYI(1, "sec_flags 0x%x", sec_flags);
+
+	pSMB2->hdr.SessionId = 0;
+
+	for (i = 0; i < SMB2_NUM_PROT; i++)
+		pSMB2->Dialects[i] = smb2protocols[i].name;
+
+	pSMB2->DialectCount = cpu_to_le16(i);
+	pSMB2->hdr.smb2_buf_length =
+		cpu_to_be32(be32_to_cpu(pSMB2->hdr.smb2_buf_length) + (i * 2));
+
+	/* only one of SMB2 signing flags may be set in SMB2 request */
+	if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN)
+		temp = SMB2_NEGOTIATE_SIGNING_REQUIRED;
+	else if (sec_flags & CIFSSEC_MAY_SIGN) /* MAY_SIGN is a single flag */
+		temp = SMB2_NEGOTIATE_SIGNING_ENABLED;
+
+	pSMB2->SecurityMode = cpu_to_le16(temp);
+
+	pSMB2->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
+
+	iov[0].iov_base = (char *)pSMB2;
+	iov[0].iov_len = be32_to_cpu(pSMB2->hdr.smb2_buf_length) + 4;
+
+	rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags);
+
+	pSMB2r = (struct smb2_negotiate_rsp *)iov[0].iov_base;
+	/*
+	 * No tcon so can't do
+	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
+	 */
+	if (rc != 0)
+		goto neg_exit;
+
+	if (pSMB2r == NULL) {
+		rc = -EIO;
+		goto neg_exit;
+	}
+
+	cFYI(1, "mode 0x%x", pSMB2r->SecurityMode);
+
+	if (pSMB2r->DialectRevision == smb2protocols[SMB21_PROT].name)
+		cFYI(1, "negotiated smb2.1 dialect");
+	else if (pSMB2r->DialectRevision == smb2protocols[SMB2_PROT].name)
+		cFYI(1, "negotiated smb2 dialect");
+	else {
+		cERROR(1, "Illegal dialect returned by server %d",
+			   le16_to_cpu(pSMB2r->DialectRevision));
+		rc = -EIO;
+		goto neg_exit;
+	}
+	ses->server->dialect = le16_to_cpu(pSMB2r->DialectRevision);
+
+	ses->server->maxBuf = le32_to_cpu(pSMB2r->MaxTransactSize);
+	ses->server->max_read = le32_to_cpu(pSMB2r->MaxReadSize);
+	ses->server->max_write = le32_to_cpu(pSMB2r->MaxWriteSize);
+	/* BB Do we need to validate the SecurityMode? */
+	ses->server->sec_mode = le16_to_cpu(pSMB2r->SecurityMode);
+	ses->server->capabilities = le32_to_cpu(pSMB2r->Capabilities);
+
+	security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
+					       &pSMB2r->hdr);
+	if (blob_length == 0) {
+		cERROR(1, "missing security blob on negprot");
+		rc = -EIO;
+		goto neg_exit;
+	}
+#ifdef CONFIG_SMB2_ASN1  /* BB REMOVEME when updated asn1.c ready */
+	rc = decode_neg_token_init(security_blob, blob_length,
+				   &ses->server->sec_type);
+	if (rc == 1)
+		rc = 0;
+	else if (rc == 0) {
+		rc = -EIO;
+		goto neg_exit;
+	}
+#endif
+
+neg_exit:
+	free_rsp_buf(resp_buftype, pSMB2r);
+	return rc;
+}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 0a17588..8eeef10 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -142,4 +142,43 @@ struct smb2_err_rsp {
 	__u8   ErrorData[1];  /* variable length */
 } __packed;
 
+struct smb2_negotiate_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize; /* Must be 36 */
+	__le16 DialectCount;
+	__le16 SecurityMode;
+	__le16 Reserved;	/* MBZ */
+	__le32 Capabilities;
+	__u8   ClientGUID[16];	/* MBZ */
+	__le64 ClientStartTime;	/* MBZ */
+	__le16 Dialects[2]; /* variable length */ /* Must include 0x0202 */
+} __packed;
+
+/* SecurityMode flags */
+#define	SMB2_NEGOTIATE_SIGNING_ENABLED	0x0001
+#define SMB2_NEGOTIATE_SIGNING_REQUIRED	0x0002
+/* Capabilities flags */
+#define SMB2_GLOBAL_CAP_DFS		0x00000001
+#define SMB2_GLOBAL_CAP_LEASING		0x00000002 /* Resp only New to SMB2.1 */
+#define SMB2_GLOBAL_CAP_LARGE_MTU	0X00000004 /* Resp only New to SMB2.1 */
+
+struct smb2_negotiate_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 65 */
+	__le16 SecurityMode;
+	__le16 DialectRevision; /* Should be 0x0202 */
+	__le16 Reserved;	/* MBZ */
+	__u8   ServerGUID[16];
+	__le32 Capabilities;
+	__le32 MaxTransactSize;
+	__le32 MaxReadSize;
+	__le32 MaxWriteSize;
+	__le64 SystemTime;	/* MBZ */
+	__le64 ServerStartTime;
+	__le16 SecurityBufferOffset;
+	__le16 SecurityBufferLength;
+	__le32 Reserved2;	/* may be any value, Ignore */
+	__u8   Buffer[1];	/* variable length GSS security buffer */
+} __packed;
+
 #endif				/* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 19bf987..a4c3c3d 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -35,10 +35,17 @@ struct statfs;
 extern int map_smb2_to_linux_error(char *buf, bool log_err);
 extern int smb2_check_message(char *buf, unsigned int length);
 extern unsigned int smb2_calc_size(struct smb2_hdr *hdr);
+extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
 
 extern int smb2_check_receive(struct mid_q_entry *mid,
 			      struct TCP_Server_Info *server, bool log_error);
 extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
 			      unsigned int nvec, struct mid_q_entry **ret_mid);
 
+/*
+ *  SMB2 Worker functions - most of protocol specific implementation details
+ *  are contained within these calls
+ */
+extern int SMB2_negotiate(const int xid, struct cifs_ses *ses);
+
 #endif			/* _SMB2PROTO_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/22] CIFS: Add session setup/logoff capability for SMB2
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (5 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 07/22] CIFS: Add capability to send SMB2 negotiate message Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 09/22] CIFS: Add tree connect/disconnect " Pavel Shilovsky
                     ` (13 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/cifsglob.h  |    3 +
 fs/cifs/ntlmssp.h   |   10 +++
 fs/cifs/sess.c      |    6 +-
 fs/cifs/smb2misc.c  |    5 +
 fs/cifs/smb2ops.c   |    2 +
 fs/cifs/smb2pdu.c   |  226 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.h   |   37 +++++++++
 fs/cifs/smb2proto.h |    3 +
 8 files changed, 289 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 119c501..fb9c8ff 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -498,6 +498,9 @@ struct cifs_ses {
 	struct session_key auth_key;
 	struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
 	bool need_reconnect:1; /* connection reset, uid now invalid */
+#ifdef CONFIG_CIFS_SMB2
+	__u16 session_flags;
+#endif /* CONFIG_CIFS_SMB2 */
 };
 /* no more than one of the following three session flags may be set */
 #define CIFS_SES_NT4 1
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 5d52e4a..848249f 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -126,3 +126,13 @@ typedef struct _AUTHENTICATE_MESSAGE {
 	   do not set the version is present flag */
 	char UserString[0];
 } __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+
+/*
+ * Size of the session key (crypto key encrypted with the password
+ */
+
+int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
+void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
+int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen,
+			struct cifs_ses *ses,
+			const struct nls_table *nls_cp);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 16b2083..c9a5add 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -364,7 +364,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 	return rc;
 }
 
-static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
+int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 				    struct cifs_ses *ses)
 {
 	unsigned int tioffset; /* challenge message target info area */
@@ -415,7 +415,7 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 
 /* We do not malloc the blob, it is passed in pbuffer, because
    it is fixed size, and small, making this approach cleaner */
-static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
+void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
 					 struct cifs_ses *ses)
 {
 	NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
@@ -451,7 +451,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
 /* We do not malloc the blob, it is passed in pbuffer, because its
    maximum possible size is fixed and small, making this approach cleaner.
    This function returns the length of the data in the blob */
-static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+int build_ntlmssp_auth_blob(unsigned char *pbuffer,
 					u16 *buflen,
 				   struct cifs_ses *ses,
 				   const struct nls_table *nls_cp)
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 1cea426..b690852 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -223,6 +223,11 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 		    ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
 		break;
 	case SMB2_SESSION_SETUP:
+		*off = le16_to_cpu(
+		    ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset);
+		*len = le16_to_cpu(
+		    ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
+		break;
 	case SMB2_CREATE:
 	case SMB2_READ:
 	case SMB2_QUERY_INFO:
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index b980d18..b642184 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -169,6 +169,8 @@ struct smb_version_operations smb21_operations = {
 	.dump_detail = smb2_dump_detail,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
+	.sess_setup = SMB2_sess_setup,
+	.logoff = SMB2_logoff,
 };
 
 struct smb_version_values smb21_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 21e291a..74045b4 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -331,3 +331,229 @@ neg_exit:
 	free_rsp_buf(resp_buftype, pSMB2r);
 	return rc;
 }
+
+int
+SMB2_sess_setup(const int xid, struct cifs_ses *ses,
+		const struct nls_table *nls_cp)
+{
+	struct smb2_sess_setup_req *pSMB2;
+	struct smb2_sess_setup_rsp *pSMB2r = NULL;
+	struct kvec iov[2];
+	int rc = 0;
+	int resp_buftype;
+	__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
+	struct TCP_Server_Info *server;
+	unsigned int sec_flags;
+	u8 temp = 0;
+	u16 blob_length = 0;
+	char *security_blob;
+	char *ntlmssp_blob = NULL;
+	bool use_spnego = false; /* else use raw ntlmssp */
+
+	cFYI(1, "Session Setup");
+
+	if (ses->server)
+		server = ses->server;
+	else {
+		rc = -EIO;
+		return rc;
+	}
+
+	/*
+	 * If memory allocation is successful, caller of this function
+	 * frees it.
+	 */
+	ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
+	if (!ses->ntlmssp)
+		return -ENOMEM;
+
+	ses->server->secType = RawNTLMSSP;
+
+ssetup_ntlmssp_authenticate:
+	if (phase == NtLmChallenge)
+		phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
+
+	rc = small_smb2_init(SMB2_SESSION_SETUP, NULL, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	/* if any of auth flags (ie not sign or seal) are overriden use them */
+	if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
+		sec_flags = ses->overrideSecFlg;  /* BB FIXME fix sign flags?*/
+	else /* if override flags set only sign/seal OR them with global auth */
+		sec_flags = global_secflags | ses->overrideSecFlg;
+
+	cFYI(1, "sec_flags 0x%x", sec_flags);
+
+	pSMB2->hdr.SessionId = 0; /* First session, not a reauthenticate */
+	pSMB2->VcNumber = 0; /* MBZ */
+	/* to enable echos and oplocks */
+	pSMB2->hdr.CreditRequest = cpu_to_le16(3);
+
+	/* only one of SMB2 signing flags may be set in SMB2 request */
+	if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN)
+		temp = SMB2_NEGOTIATE_SIGNING_REQUIRED;
+	else if (ses->server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED)
+		temp = SMB2_NEGOTIATE_SIGNING_REQUIRED;
+	else if (sec_flags & CIFSSEC_MAY_SIGN) /* MAY_SIGN is a single flag */
+		temp = SMB2_NEGOTIATE_SIGNING_ENABLED;
+
+	pSMB2->SecurityMode = temp;
+
+	/* We only support the DFS cap (others are currently undefined) */
+	pSMB2->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS
+						& ses->server->capabilities);
+	pSMB2->Channel = 0; /* MBZ */
+	iov[0].iov_base = (char *)pSMB2;
+	iov[0].iov_len = be32_to_cpu(pSMB2->hdr.smb2_buf_length)
+					+ 4 /* rfc1001 len */ - 1 /* pad */;
+	if (phase == NtLmNegotiate) {
+		ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
+					GFP_KERNEL);
+		if (ntlmssp_blob == NULL) {
+			rc = -ENOMEM;
+			goto ssetup_exit;
+		}
+
+		build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
+		if (use_spnego) {
+			/* blob_length = build_spnego_ntlmssp_blob(
+					&security_blob,
+					sizeof(struct _NEGOTIATE_MESSAGE),
+					ntlmssp_blob); */
+			/* BB eventually need to add this */
+			cERROR(1, "spnego not supported for SMB2 yet");
+			rc = -EOPNOTSUPP;
+			kfree(ntlmssp_blob);
+			goto ssetup_exit;
+		} else {
+			blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
+			/* with raw NTLMSSP we don't encapsulate in SPNEGO */
+			security_blob = ntlmssp_blob;
+		}
+	} else if (phase == NtLmAuthenticate) {
+		pSMB2->hdr.SessionId = ses->Suid;
+		ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500,
+					GFP_KERNEL);
+		if (ntlmssp_blob == NULL) {
+			cERROR(1, "failed to malloc ntlmssp blob");
+			rc = -ENOMEM;
+			goto ssetup_exit;
+		}
+		rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length,
+					ses, nls_cp);
+		if (rc) {
+			cFYI(1, "build_ntlmssp_auth_blob failed %d", rc);
+			goto ssetup_exit; /* BB double check error handling */
+		}
+		if (use_spnego) {
+			/* blob_length = build_spnego_ntlmssp_blob(
+							&security_blob,
+							blob_length,
+							ntlmssp_blob); */
+			cERROR(1, "spnego not supported for SMB2 yet");
+			rc = -EOPNOTSUPP;
+			kfree(ntlmssp_blob);
+			goto ssetup_exit;
+		} else {
+			security_blob = ntlmssp_blob;
+		}
+	} else {
+		cERROR(1, "illegal ntlmssp phase");
+		rc = -EIO;
+		goto ssetup_exit;
+	}
+
+	/* Testing shows that buffer offset must be at location of Buffer[0] */
+	pSMB2->SecurityBufferOffset = cpu_to_le16(
+			sizeof(struct smb2_sess_setup_req) - 1 /* pad */
+			- 4 /* rfc1001 len */);
+	pSMB2->SecurityBufferLength = cpu_to_le16(blob_length);
+	iov[1].iov_base = security_blob;
+	iov[1].iov_len = blob_length;
+
+	pSMB2->hdr.smb2_buf_length =
+		cpu_to_be32(be32_to_cpu(pSMB2->hdr.smb2_buf_length)
+			    - 1 /* pad */ + blob_length);
+
+	/* BB add code to build os and lm fields */
+
+	rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, CIFS_LOG_ERROR);
+
+	kfree(security_blob);
+	pSMB2r = (struct smb2_sess_setup_rsp *)iov[0].iov_base;
+	if (pSMB2r->hdr.Status ==
+			cpu_to_le32(STATUS_MORE_PROCESSING_REQUIRED)) {
+		if (phase != NtLmNegotiate) {
+			cERROR(1, "Unexpected more processing error");
+			goto ssetup_exit;
+		}
+		if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
+			le16_to_cpu(pSMB2r->SecurityBufferOffset)) {
+			cERROR(1, "Invalid security buffer offset %d",
+				    le16_to_cpu(pSMB2r->SecurityBufferOffset));
+			rc = -EIO;
+			goto ssetup_exit;
+		}
+
+		/* NTLMSSP Negotiate sent now processing challenge (response) */
+		phase = NtLmChallenge; /* process ntlmssp challenge */
+		rc = 0; /* MORE_PROCESSING is not an error here but expected */
+		ses->Suid = pSMB2r->hdr.SessionId;
+		rc = decode_ntlmssp_challenge(pSMB2r->Buffer,
+				le16_to_cpu(pSMB2r->SecurityBufferLength), ses);
+	}
+
+	/* BB eventually add code for SPNEGO decoding of NtlmChallenge blob,
+	   but at least the raw NTLMSSP case works */
+
+	/*
+	 * No tcon so can't do
+	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
+	 */
+	if (rc != 0)
+		goto ssetup_exit;
+
+	if (pSMB2r == NULL) {
+		rc = -EIO;
+		goto ssetup_exit;
+	}
+
+	ses->session_flags = le16_to_cpu(pSMB2r->SessionFlags);
+ssetup_exit:
+	free_rsp_buf(resp_buftype, pSMB2r);
+
+	/* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
+	if ((phase == NtLmChallenge) && (rc == 0))
+		goto ssetup_ntlmssp_authenticate;
+	return rc;
+}
+
+int
+SMB2_logoff(const int xid, struct cifs_ses *ses)
+{
+	struct smb2_logoff_req *pSMB2; /* response is also trivial struct */
+	int rc = 0;
+	struct TCP_Server_Info *server;
+
+	cFYI(1, "disconnect session %p", ses);
+
+	if (ses && (ses->server))
+		server = ses->server;
+	else
+		return -EIO;
+
+	rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	 /* since no tcon, smb2_init can not do this, so do here */
+	pSMB2->hdr.SessionId = ses->Suid;
+
+	rc = SendReceiveNoRsp(xid, ses, (char *) &pSMB2->hdr, 0);
+	/*
+	 * No tcon so can't do
+	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
+	 */
+	return rc;
+}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 8eeef10..e63b529 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -181,4 +181,41 @@ struct smb2_negotiate_rsp {
 	__u8   Buffer[1];	/* variable length GSS security buffer */
 } __packed;
 
+struct smb2_sess_setup_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize; /* Must be 25 */
+	__u8   VcNumber;
+	__u8   SecurityMode;
+	__le32 Capabilities;
+	__le32 Channel;
+	__le16 SecurityBufferOffset;
+	__le16 SecurityBufferLength;
+	__le64 PreviousSessionId;
+	__u8   Buffer[1];	/* variable length GSS security buffer */
+} __packed;
+
+/* Currently defined SessionFlags */
+#define SMB2_SESSION_FLAG_IS_GUEST	0x0001
+#define SMB2_SESSION_FLAG_IS_NULL	0x0002
+struct smb2_sess_setup_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize; /* Must be 9 */
+	__le16 SessionFlags;
+	__le16 SecurityBufferOffset;
+	__le16 SecurityBufferLength;
+	__u8   Buffer[1];	/* variable length GSS security buffer */
+} __packed;
+
+struct smb2_logoff_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 4 */
+	__le16 Reserved;
+} __packed;
+
+struct smb2_logoff_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 4 */
+	__le16 Reserved;
+} __packed;
+
 #endif				/* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index a4c3c3d..f4375bf 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -47,5 +47,8 @@ extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
  *  are contained within these calls
  */
 extern int SMB2_negotiate(const int xid, struct cifs_ses *ses);
+extern int SMB2_sess_setup(const int xid, struct cifs_ses *ses,
+			   const struct nls_table *nls_cp);
+extern int SMB2_logoff(const int xid, struct cifs_ses *ses);
 
 #endif			/* _SMB2PROTO_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/22] CIFS: Add tree connect/disconnect capability for SMB2
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (6 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 08/22] CIFS: Add session setup/logoff capability for SMB2 Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:39   ` [PATCH 10/22] CIFS: Process reconnects for SMB2 shares Pavel Shilovsky
                     ` (12 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/cifs_unicode.c |    1 -
 fs/cifs/cifs_unicode.h |    1 -
 fs/cifs/cifsglob.h     |   11 +++-
 fs/cifs/smb2ops.c      |    2 +
 fs/cifs/smb2pdu.c      |  161 +++++++++++++++++++++++++++++++++++++++++++++++-
 fs/cifs/smb2pdu.h      |   57 +++++++++++++++++
 fs/cifs/smb2proto.h    |    4 +
 7 files changed, 232 insertions(+), 5 deletions(-)

diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index fbb9da9..97c1d42 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -330,4 +330,3 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
 ctoUTF16_out:
 	return i;
 }
-
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index a513a54..a44c6eb 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -84,7 +84,6 @@ char *cifs_strndup_from_utf16(const char *src, const int maxlen,
 			      const struct nls_table *codepage);
 extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
 			      const struct nls_table *cp, int mapChars);
-
 #endif
 
 /*
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index fb9c8ff..3215026 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -522,7 +522,7 @@ struct cifs_tcon {
 	char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
 	char *nativeFileSystem;
 	char *password;		/* for share-level security */
-	__u16 tid;		/* The 2 byte tree id */
+	__u32 tid;		/* The 4 byte tree id */
 	__u16 Flags;		/* optional support bits */
 	enum statusEnum tidStatus;
 #ifdef CONFIG_CIFS_STATS
@@ -578,6 +578,15 @@ struct cifs_tcon {
 	bool local_lease:1; /* check leases (only) on local system not remote */
 	bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
 	bool need_reconnect:1; /* connection reset, tid now invalid */
+#ifdef CONFIG_CIFS_SMB2
+	bool print:1;		/* set if connection to printer share */
+	bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
+	__u32 capabilities;
+	__u32 share_flags;
+	__u32 maximal_access;
+	__u32 vol_serial_number;
+	__le64 vol_create_time;
+#endif /* CONFIG_CIFS_SMB2 */
 #ifdef CONFIG_CIFS_FSCACHE
 	u64 resource_id;		/* server resource id */
 	struct fscache_cookie *fscache;	/* cookie for share */
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index b642184..a904b35 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -171,6 +171,8 @@ struct smb_version_operations smb21_operations = {
 	.negotiate = smb2_negotiate,
 	.sess_setup = SMB2_sess_setup,
 	.logoff = SMB2_logoff,
+	.tree_connect = SMB2_tcon,
+	.tree_disconnect = SMB2_tdis,
 };
 
 struct smb_version_values smb21_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 74045b4..3d1d51d 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -114,8 +114,8 @@ smb2_hdr_assemble(struct smb2_hdr *buffer, __le16 smb2_cmd /* command */ ,
 		buffer->SessionId = tcon->ses->Suid;
 	/* BB check following DFS flags BB */
 	/* BB do we have to add check for SHI1005_FLAGS_DFS_ROOT too? */
-	/* if (tcon->share_flags & SHI1005_FLAGS_DFS)
-		buffer->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
+	if (tcon->share_flags & SHI1005_FLAGS_DFS)
+		buffer->Flags |= SMB2_FLAGS_DFS_OPERATIONS;
 	/* BB how does SMB2 do case sensitive? */
 	/* if (tcon->nocase)
 		buffer->Flags |= SMBFLG_CASELESS; */
@@ -557,3 +557,160 @@ SMB2_logoff(const int xid, struct cifs_ses *ses)
 	 */
 	return rc;
 }
+
+static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
+{
+	/* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[code]); */
+}
+
+#define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
+
+int
+SMB2_tcon(const int xid, struct cifs_ses *ses, const char *tree,
+	  struct cifs_tcon *tcon, const struct nls_table *cp)
+{
+	struct smb2_tree_connect_req *pSMB2;
+	struct smb2_tree_connect_rsp *pSMB2r = NULL;
+	struct kvec iov[2];
+	int rc = 0;
+	int resp_buftype;
+	int unc_path_len;
+	struct TCP_Server_Info *server;
+	__le16 *unc_path = NULL;
+
+	cFYI(1, "TCON");
+
+	if ((ses->server) && tree)
+		server = ses->server;
+	else
+		return -EIO;
+
+	if (tcon && tcon->bad_network_name)
+		return -ENOENT;
+
+	unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
+	if (unc_path == NULL)
+		return -ENOMEM;
+
+	unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1;
+	unc_path_len *= 2;
+	if (unc_path_len < 2) {
+		kfree(unc_path);
+		return -EINVAL;
+	}
+
+	rc = small_smb2_init(SMB2_TREE_CONNECT, tcon, (void **) &pSMB2);
+	if (rc) {
+		kfree(unc_path);
+		return rc;
+	}
+
+	if (tcon == NULL) {
+		/* since no tcon, smb2_init can not do this, so do here */
+		pSMB2->hdr.SessionId = ses->Suid;
+		if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
+			pSMB2->hdr.Flags |= SMB2_FLAGS_SIGNED;
+	}
+
+	iov[0].iov_base = (char *)pSMB2;
+	iov[0].iov_len = be32_to_cpu(pSMB2->hdr.smb2_buf_length)
+					+ 4 /* rfc1001 len */ - 1 /* pad */;
+
+	/* Testing shows that buffer offset must be at location of Buffer[0] */
+	pSMB2->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
+			- 1 /* pad */ - 4 /* do not count rfc1001 len field */);
+	pSMB2->PathLength = cpu_to_le16(unc_path_len - 2);
+	iov[1].iov_base = unc_path;
+	iov[1].iov_len = unc_path_len;
+
+	pSMB2->hdr.smb2_buf_length =
+		cpu_to_be32(be32_to_cpu(pSMB2->hdr.smb2_buf_length)
+			    - 1 /* pad */ + unc_path_len);
+
+	rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 0);
+	pSMB2r = (struct smb2_tree_connect_rsp *)iov[0].iov_base;
+
+	if (rc != 0) {
+		if (tcon) {
+			cifs_stats_fail_inc(tcon, SMB2TREE_CONNECT);
+			tcon->need_reconnect = true;
+		}
+		goto tcon_error_exit;
+	}
+
+	if (pSMB2r == NULL) {
+		rc = -EIO;
+		goto tcon_exit;
+	}
+
+	if (tcon == NULL) {
+		ses->ipc_tid = pSMB2r->hdr.TreeId;
+		goto tcon_exit;
+	}
+
+	if (pSMB2r->ShareType & SMB2_SHARE_TYPE_DISK)
+		cFYI(1, "connection to disk share");
+	else if (pSMB2r->ShareType & SMB2_SHARE_TYPE_PIPE) {
+		tcon->ipc = true;
+		cFYI(1, "connection to pipe share");
+	} else if (pSMB2r->ShareType & SMB2_SHARE_TYPE_PRINT) {
+		tcon->print = true;
+		cFYI(1, "connection to printer");
+	} else {
+		cERROR(1, "unknown share type %d", pSMB2r->ShareType);
+		rc = -EOPNOTSUPP;
+		goto tcon_error_exit;
+	}
+
+	tcon->share_flags = le32_to_cpu(pSMB2r->ShareFlags);
+	tcon->maximal_access = le32_to_cpu(pSMB2r->MaximalAccess);
+	tcon->tidStatus = CifsGood;
+	tcon->need_reconnect = false;
+	tcon->tid = pSMB2r->hdr.TreeId;
+	strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
+
+	if ((pSMB2r->Capabilities & SMB2_SHARE_CAP_DFS) &&
+	    ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
+		cERROR(1, "DFS capability contradicts DFS flag");
+
+tcon_exit:
+	free_rsp_buf(resp_buftype, pSMB2r);
+	kfree(unc_path);
+	return rc;
+
+tcon_error_exit:
+	if (pSMB2r->hdr.Status == cpu_to_le32(STATUS_BAD_NETWORK_NAME)) {
+		cERROR(1, "BAD_NETWORK_NAME: %s", tree);
+		tcon->bad_network_name = true;
+	}
+	goto tcon_exit;
+}
+
+int
+SMB2_tdis(const int xid, struct cifs_tcon *tcon)
+{
+	struct smb2_tree_disconnect_req *pSMB2; /* response is trivial */
+	int rc = 0;
+	struct TCP_Server_Info *server;
+	struct cifs_ses *ses = tcon->ses;
+
+	cFYI(1, "Tree Disconnect");
+
+	if (ses && (ses->server))
+		server = ses->server;
+	else
+		return -EIO;
+
+	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
+		return 0;
+
+	rc = small_smb2_init(SMB2_TREE_DISCONNECT, tcon, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	rc = SendReceiveNoRsp(xid, ses, (char *)&pSMB2->hdr, 0);
+	if (rc)
+		cifs_stats_fail_inc(tcon, SMB2TREE_DISCONNECT);
+
+	return rc;
+}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index e63b529..007de36 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -218,4 +218,61 @@ struct smb2_logoff_rsp {
 	__le16 Reserved;
 } __packed;
 
+struct smb2_tree_connect_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 9 */
+	__le16 Reserved;
+	__le16 PathOffset;
+	__le16 PathLength;
+	__u8   Buffer[1];	/* variable length */
+} __packed;
+
+struct smb2_tree_connect_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 16 */
+	__u8   ShareType;  /* see below */
+	__u8   Reserved;
+	__le32 ShareFlags; /* see below */
+	__le32 Capabilities; /* see below */
+	__le32 MaximalAccess;
+} __packed;
+
+/* Possible ShareType values */
+#define SMB2_SHARE_TYPE_DISK	0x01
+#define SMB2_SHARE_TYPE_PIPE	0x02
+#define	SMB2_SHARE_TYPE_PRINT	0x03
+
+/*
+ * Possible ShareFlags - exactly one and only one of the first 4 caching flags
+ * must be set (any of the remaining, SHI1005, flags may be set individually
+ * or in combination.
+ */
+#define SMB2_SHAREFLAG_MANUAL_CACHING			0x00000000
+#define SMB2_SHAREFLAG_AUTO_CACHING			0x00000010
+#define SMB2_SHAREFLAG_VDO_CACHING			0x00000020
+#define SMB2_SHAREFLAG_NO_CACHING			0x00000030
+#define SHI1005_FLAGS_DFS				0x00000001
+#define SHI1005_FLAGS_DFS_ROOT				0x00000002
+#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS		0x00000100
+#define SHI1005_FLAGS_FORCE_SHARED_DELETE		0x00000200
+#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING		0x00000400
+#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM	0x00000800
+#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK		0x00001000
+#define SHI1005_FLAGS_ENABLE_HASH			0x00002000
+
+/* Possible share capabilities */
+#define SMB2_SHARE_CAP_DFS	cpu_to_le32(0x00000008)
+
+struct smb2_tree_disconnect_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 4 */
+	__le16 Reserved;
+} __packed;
+
+struct smb2_tree_disconnect_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 4 */
+	__le16 Reserved;
+} __packed;
+
 #endif				/* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index f4375bf..0d51482 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -50,5 +50,9 @@ extern int SMB2_negotiate(const int xid, struct cifs_ses *ses);
 extern int SMB2_sess_setup(const int xid, struct cifs_ses *ses,
 			   const struct nls_table *nls_cp);
 extern int SMB2_logoff(const int xid, struct cifs_ses *ses);
+extern int SMB2_tcon(const int xid, struct cifs_ses *ses,
+		     const char *tree, struct cifs_tcon *tcon,
+		     const struct nls_table *);
+extern int SMB2_tdis(const int xid, struct cifs_tcon *tcon);
 
 #endif			/* _SMB2PROTO_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/22] CIFS: Process reconnects for SMB2 shares
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (7 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 09/22] CIFS: Add tree connect/disconnect " Pavel Shilovsky
@ 2012-06-19 12:39   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 11/22] CIFS: Move getting dfs referalls to ops struct Pavel Shilovsky
                     ` (11 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:39 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/cifsproto.h |    1 +
 fs/cifs/cifssmb.c   |   21 +++++---
 fs/cifs/connect.c   |    3 +
 fs/cifs/smb2pdu.c   |  127 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 143 insertions(+), 9 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 19987a7..6152571 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -170,6 +170,7 @@ extern struct smb_vol *cifs_get_volume_info(char *mount_data,
 					    const char *devname);
 extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
 extern void cifs_umount(struct cifs_sb_info *);
+extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
 
 #if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
 extern void cifs_dfs_release_automount_timer(void);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index fbc5628..c3bfe9a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -88,24 +88,29 @@ static struct {
 
 /* Forward declarations */
 
-/* Mark as invalid, all open files on tree connections since they
-   were closed when session to server was lost */
-static void mark_open_files_invalid(struct cifs_tcon *pTcon)
+/*
+ * Mark as invalid, all open files on tree connections since they
+ * were closed when session to server was lost.
+ */
+void
+cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
 {
 	struct cifsFileInfo *open_file = NULL;
 	struct list_head *tmp;
 	struct list_head *tmp1;
 
-/* list all files open on tree connection and mark them invalid */
+	/* list all files open on tree connection and mark them invalid */
 	spin_lock(&cifs_file_list_lock);
-	list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
+	list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
 		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
 		open_file->invalidHandle = true;
 		open_file->oplock_break_cancelled = true;
 	}
 	spin_unlock(&cifs_file_list_lock);
-	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
-	   to this tcon */
+	/*
+	 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
+	 * to this tcon.
+	 */
 }
 
 /* reconnect the socket, tcon, and smb session if needed */
@@ -185,7 +190,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 		goto out;
 	}
 
-	mark_open_files_invalid(tcon);
+	cifs_mark_open_files_invalid(tcon);
 	rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
 	mutex_unlock(&ses->session_mutex);
 	cFYI(1, "reconnect tcon rc = %d", rc);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d45df03..d6fc429 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -316,6 +316,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
 		server->tcpStatus = CifsNeedReconnect;
 	spin_unlock(&GlobalMid_Lock);
 	server->maxBuf = 0;
+#ifdef CONFIG_CIFS_SMB2
+	server->max_read = 0;
+#endif
 
 	cFYI(1, "Reconnecting tcp session");
 
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 3d1d51d..9ec0bfe 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -131,7 +131,132 @@ static int
 smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 {
 	int rc = 0;
-	/* BB add missing code here */
+	struct nls_table *nls_codepage;
+	struct cifs_ses *ses;
+	struct TCP_Server_Info *server;
+
+	/*
+	 * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
+	 * check for tcp and smb session status done differently
+	 * for those three - in the calling routine.
+	 */
+	if (tcon == NULL)
+		return rc;
+
+	if (smb2_command == SMB2_TREE_CONNECT)
+		return rc;
+
+	if (tcon->tidStatus == CifsExiting) {
+		/*
+		 * only tree disconnect, open, and write,
+		 * (and ulogoff which does not have tcon)
+		 * are allowed as we start force umount.
+		 */
+		if ((smb2_command != SMB2_WRITE) &&
+		   (smb2_command != SMB2_CREATE) &&
+		   (smb2_command != SMB2_TREE_DISCONNECT)) {
+			cFYI(1, "can not send cmd %d while umounting",
+				smb2_command);
+			return -ENODEV;
+		}
+	}
+	if ((!tcon->ses) || (tcon->ses->status == CifsExiting) ||
+	    (!tcon->ses->server))
+		return -EIO;
+
+	ses = tcon->ses;
+	server = ses->server;
+
+	/*
+	 * Give demultiplex thread up to 10 seconds to reconnect, should be
+	 * greater than cifs socket timeout which is 7 seconds
+	 */
+	while (server->tcpStatus == CifsNeedReconnect) {
+		/*
+		 * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
+		 * here since they are implicitly done when session drops.
+		 */
+		switch (smb2_command) {
+		/*
+		 * BB Should we keep oplock break and add flush to exceptions?
+		 */
+		case SMB2_TREE_DISCONNECT:
+		case SMB2_CANCEL:
+		case SMB2_CLOSE:
+		case SMB2_OPLOCK_BREAK:
+			return -EAGAIN;
+		}
+
+		wait_event_interruptible_timeout(server->response_q,
+			(server->tcpStatus != CifsNeedReconnect), 10 * HZ);
+
+		/* are we still trying to reconnect? */
+		if (server->tcpStatus != CifsNeedReconnect)
+			break;
+
+		/*
+		 * on "soft" mounts we wait once. Hard mounts keep
+		 * retrying until process is killed or server comes
+		 * back on-line
+		 */
+		if (!tcon->retry) {
+			cFYI(1, "gave up waiting on reconnect in smb_init");
+			return -EHOSTDOWN;
+		}
+	}
+
+	if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
+		return rc;
+
+	nls_codepage = load_nls_default();
+
+	/*
+	 * need to prevent multiple threads trying to simultaneously reconnect
+	 * the same SMB session
+	 */
+	mutex_lock(&tcon->ses->session_mutex);
+	rc = cifs_negotiate_protocol(0, tcon->ses);
+	if (!rc && tcon->ses->need_reconnect)
+		rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+
+	if (rc || !tcon->need_reconnect) {
+		mutex_unlock(&tcon->ses->session_mutex);
+		goto out;
+	}
+
+	cifs_mark_open_files_invalid(tcon);
+	rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
+	mutex_unlock(&tcon->ses->session_mutex);
+	cFYI(1, "reconnect tcon rc = %d", rc);
+	if (rc)
+		goto out;
+	atomic_inc(&tconInfoReconnectCount);
+	/*
+	 * BB FIXME add code to check if wsize needs update due to negotiated
+	 * smb buffer size shrinking.
+	 */
+out:
+	/*
+	 * Check if handle based operation so we know whether we can continue
+	 * or not without returning to caller to reset file handle.
+	 */
+	/*
+	 * BB Is flush done by server on drop of tcp session? Should we special
+	 * case it and skip above?
+	 */
+	switch (smb2_command) {
+	case SMB2_FLUSH:
+	case SMB2_READ:
+	case SMB2_WRITE:
+	case SMB2_LOCK:
+	case SMB2_IOCTL:
+	case SMB2_QUERY_DIRECTORY:
+	case SMB2_CHANGE_NOTIFY:
+	case SMB2_QUERY_INFO:
+	case SMB2_SET_INFO:
+		return -EAGAIN;
+	}
+	unload_nls(nls_codepage);
 	return rc;
 }
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 11/22] CIFS: Move getting dfs referalls to ops struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (8 preceding siblings ...)
  2012-06-19 12:39   ` [PATCH 10/22] CIFS: Process reconnects for SMB2 shares Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 12/22] CIFS: Move informational tcon calls " Pavel Shilovsky
                     ` (10 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h  |    5 +++++
 fs/cifs/cifsproto.h |    8 ++++----
 fs/cifs/cifssmb.c   |    3 +--
 fs/cifs/connect.c   |    9 +++++----
 fs/cifs/smb1ops.c   |   12 ++++++++++++
 5 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 3215026..e045c31 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -162,6 +162,7 @@ struct TCP_Server_Info;
 struct cifsFileInfo;
 struct cifs_ses;
 struct cifs_tcon;
+struct dfs_info3_param;
 
 struct smb_version_operations {
 	int (*send_cancel)(struct TCP_Server_Info *, void *,
@@ -208,6 +209,10 @@ struct smb_version_operations {
 			    struct cifs_tcon *, const struct nls_table *);
 	/* close tree connecion */
 	int (*tree_disconnect)(const int, struct cifs_tcon *);
+	/* get DFS referrals */
+	int (*get_dfs_refer)(const int, struct cifs_ses *, const char *,
+			     struct dfs_info3_param **, unsigned int *,
+			     const struct nls_table *, int);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 6152571..8b5f2a6 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -223,10 +223,10 @@ extern int CIFSSMBUnixQPathInfo(const int xid,
 			const struct nls_table *nls_codepage, int remap);
 
 extern int CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
-			const unsigned char *searchName,
-			struct dfs_info3_param **target_nodes,
-			unsigned int *number_of_nodes_in_array,
-			const struct nls_table *nls_codepage, int remap);
+			   const char *searchName,
+			   struct dfs_info3_param **target_nodes,
+			   unsigned int *num_of_nodes,
+			   const struct nls_table *nls_codepage, int remap);
 
 extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo,
 			const char *old_path,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c3bfe9a..13e1c7f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4741,8 +4741,7 @@ parse_DFS_referrals_exit:
 }
 
 int
-CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
-		const unsigned char *searchName,
+CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, const char *searchName,
 		struct dfs_info3_param **target_nodes,
 		unsigned int *num_of_nodes,
 		const struct nls_table *nls_codepage, int remap)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d6fc429..5e62b3a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2772,7 +2772,7 @@ get_dfs_path(int xid, struct cifs_ses *ses, const char *old_path,
 	char *temp_unc;
 	int rc = 0;
 
-	if (!ses->server->ops->tree_connect)
+	if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
 		return -ENOSYS;
 
 	*num_referrals = 0;
@@ -2794,11 +2794,12 @@ get_dfs_path(int xid, struct cifs_ses *ses, const char *old_path,
 		kfree(temp_unc);
 	}
 	if (rc == 0)
-		rc = CIFSGetDFSRefer(xid, ses, old_path, referrals,
-				     num_referrals, nls_codepage, remap);
+		rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
+						     referrals, num_referrals,
+						     nls_codepage, remap);
 	/*
 	 * BB - map targetUNCs to dfs_info3 structures, here or in
-	 * CIFSGetDFSRefer.
+	 * ses->server->ops->get_dfs_refer.
 	 */
 
 	return rc;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index cd7fbfd..fc17951 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -410,6 +410,17 @@ cifs_negotiate(const int xid, struct cifs_ses *ses)
 	return rc;
 }
 
+static int
+cifs_get_dfs_refer(const int xid, struct cifs_ses *ses, const char *search_name,
+		   struct dfs_info3_param **target_nodes,
+		   unsigned int *num_of_nodes,
+		   const struct nls_table *nls_codepage, int remap)
+{
+	return CIFSGetDFSRefer(xid, ses, search_name, target_nodes,
+			       num_of_nodes, nls_codepage, remap);
+	/* BB map targetUNCs to dfs_info3 here or in CIFSGetDFSRefer. */
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -434,6 +445,7 @@ struct smb_version_operations smb1_operations = {
 	.logoff = CIFSSMBLogoff,
 	.tree_connect = CIFSTCon,
 	.tree_disconnect = CIFSSMBTDis,
+	.get_dfs_refer = cifs_get_dfs_refer,
 };
 
 struct smb_version_values smb1_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 12/22] CIFS: Move informational tcon calls to ops struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (9 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 11/22] CIFS: Move getting dfs referalls to ops struct Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 13/22] CIFS: Move is_path_accessible " Pavel Shilovsky
                     ` (9 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

and rename variables in cifs_mount.

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h |    2 ++
 fs/cifs/connect.c  |   51 ++++++++++++++++++++++++---------------------------
 fs/cifs/smb1ops.c  |    8 ++++++++
 3 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index e045c31..4f82900 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -213,6 +213,8 @@ struct smb_version_operations {
 	int (*get_dfs_refer)(const int, struct cifs_ses *, const char *,
 			     struct dfs_info3_param **, unsigned int *,
 			     const struct nls_table *, int);
+	/* informational QFS call */
+	void (*qfs_tcon)(const int, struct cifs_tcon *);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5e62b3a..3f6b66a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3583,9 +3583,9 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
 {
 	int rc;
 	int xid;
-	struct cifs_ses *pSesInfo;
+	struct cifs_ses *ses;
 	struct cifs_tcon *tcon;
-	struct TCP_Server_Info *srvTcp;
+	struct TCP_Server_Info *server;
 	char   *full_path;
 	struct tcon_link *tlink;
 #ifdef CONFIG_CIFS_DFS_UPCALL
@@ -3602,39 +3602,39 @@ try_mount_again:
 	if (referral_walks_count) {
 		if (tcon)
 			cifs_put_tcon(tcon);
-		else if (pSesInfo)
-			cifs_put_smb_ses(pSesInfo);
+		else if (ses)
+			cifs_put_smb_ses(ses);
 
 		FreeXid(xid);
 	}
 #endif
 	rc = 0;
 	tcon = NULL;
-	pSesInfo = NULL;
-	srvTcp = NULL;
+	ses = NULL;
+	server = NULL;
 	full_path = NULL;
 	tlink = NULL;
 
 	xid = GetXid();
 
 	/* get a reference to a tcp session */
-	srvTcp = cifs_get_tcp_session(volume_info);
-	if (IS_ERR(srvTcp)) {
-		rc = PTR_ERR(srvTcp);
+	server = cifs_get_tcp_session(volume_info);
+	if (IS_ERR(server)) {
+		rc = PTR_ERR(server);
 		bdi_destroy(&cifs_sb->bdi);
 		goto out;
 	}
 
 	/* get a reference to a SMB session */
-	pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
-	if (IS_ERR(pSesInfo)) {
-		rc = PTR_ERR(pSesInfo);
-		pSesInfo = NULL;
+	ses = cifs_get_smb_ses(server, volume_info);
+	if (IS_ERR(ses)) {
+		rc = PTR_ERR(ses);
+		ses = NULL;
 		goto mount_fail_check;
 	}
 
 	/* search for existing tcon to this server share */
-	tcon = cifs_get_tcon(pSesInfo, volume_info);
+	tcon = cifs_get_tcon(ses, volume_info);
 	if (IS_ERR(tcon)) {
 		rc = PTR_ERR(tcon);
 		tcon = NULL;
@@ -3655,11 +3655,9 @@ try_mount_again:
 	} else
 		tcon->unix_ext = 0; /* server does not support them */
 
-	/* do not care if following two calls succeed - informational */
-	if (!tcon->ipc) {
-		CIFSSMBQFSDeviceInfo(xid, tcon);
-		CIFSSMBQFSAttributeInfo(xid, tcon);
-	}
+	/* do not care if a following call succeed - informational */
+	if (!tcon->ipc && server->ops->qfs_tcon)
+		server->ops->qfs_tcon(xid, tcon);
 
 	cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
 	cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
@@ -3677,8 +3675,8 @@ remote_path_check:
 	 * Chase the referral if found, otherwise continue normally.
 	 */
 	if (referral_walks_count == 0) {
-		int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
-						cifs_sb, false);
+		int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
+						false);
 		if (!refrc) {
 			referral_walks_count++;
 			goto try_mount_again;
@@ -3716,8 +3714,7 @@ remote_path_check:
 			goto mount_fail_check;
 		}
 
-		rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
-					 true);
+		rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
 
 		if (!rc) {
 			referral_walks_count++;
@@ -3739,7 +3736,7 @@ remote_path_check:
 		goto mount_fail_check;
 	}
 
-	tlink->tl_uid = pSesInfo->linux_uid;
+	tlink->tl_uid = ses->linux_uid;
 	tlink->tl_tcon = tcon;
 	tlink->tl_time = jiffies;
 	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
@@ -3760,10 +3757,10 @@ mount_fail_check:
 		/* up accidentally freeing someone elses tcon struct */
 		if (tcon)
 			cifs_put_tcon(tcon);
-		else if (pSesInfo)
-			cifs_put_smb_ses(pSesInfo);
+		else if (ses)
+			cifs_put_smb_ses(ses);
 		else
-			cifs_put_tcp_session(srvTcp);
+			cifs_put_tcp_session(server);
 		bdi_destroy(&cifs_sb->bdi);
 	}
 
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index fc17951..00cae9e 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -421,6 +421,13 @@ cifs_get_dfs_refer(const int xid, struct cifs_ses *ses, const char *search_name,
 	/* BB map targetUNCs to dfs_info3 here or in CIFSGetDFSRefer. */
 }
 
+static void
+cifs_qfs_tcon(const int xid, struct cifs_tcon *tcon)
+{
+	CIFSSMBQFSDeviceInfo(xid, tcon);
+	CIFSSMBQFSAttributeInfo(xid, tcon);
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -446,6 +453,7 @@ struct smb_version_operations smb1_operations = {
 	.tree_connect = CIFSTCon,
 	.tree_disconnect = CIFSSMBTDis,
 	.get_dfs_refer = cifs_get_dfs_refer,
+	.qfs_tcon = cifs_qfs_tcon,
 };
 
 struct smb_version_values smb1_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 13/22] CIFS: Move is_path_accessible to ops struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (10 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 12/22] CIFS: Move informational tcon calls " Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 14/22] CIFS: Add SMB2 support for is_path_accessible Pavel Shilovsky
                     ` (8 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h |    3 +++
 fs/cifs/connect.c  |   31 ++++++-------------------------
 fs/cifs/smb1ops.c  |   25 +++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 4f82900..7f5cb14 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -215,6 +215,9 @@ struct smb_version_operations {
 			     const struct nls_table *, int);
 	/* informational QFS call */
 	void (*qfs_tcon)(const int, struct cifs_tcon *);
+	/* check if a path is accessible or not */
+	int (*is_path_accessible)(const int, struct cifs_tcon *,
+				  struct cifs_sb_info *, const char *);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3f6b66a..a1f301f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3385,30 +3385,6 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
 	return rsize;
 }
 
-static int
-is_path_accessible(int xid, struct cifs_tcon *tcon,
-		   struct cifs_sb_info *cifs_sb, const char *full_path)
-{
-	int rc;
-	FILE_ALL_INFO *pfile_info;
-
-	pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
-	if (pfile_info == NULL)
-		return -ENOMEM;
-
-	rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
-			      0 /* not legacy */, cifs_sb->local_nls,
-			      cifs_sb->mnt_cifs_flags &
-				CIFS_MOUNT_MAP_SPECIAL_CHR);
-
-	if (rc == -EOPNOTSUPP || rc == -EINVAL)
-		rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
-				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-				  CIFS_MOUNT_MAP_SPECIAL_CHR);
-	kfree(pfile_info);
-	return rc;
-}
-
 static void
 cleanup_volume_info_contents(struct smb_vol *volume_info)
 {
@@ -3686,13 +3662,18 @@ remote_path_check:
 
 	/* check if a whole path is not remote */
 	if (!rc && tcon) {
+		if (!server->ops->is_path_accessible) {
+			rc = -ENOSYS;
+			goto mount_fail_check;
+		}
 		/* build_path_to_root works only when we have a valid tcon */
 		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
 		if (full_path == NULL) {
 			rc = -ENOMEM;
 			goto mount_fail_check;
 		}
-		rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
+		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
+						     full_path);
 		if (rc != 0 && rc != -EREMOTE) {
 			kfree(full_path);
 			goto mount_fail_check;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 00cae9e..554ecba 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -428,6 +428,30 @@ cifs_qfs_tcon(const int xid, struct cifs_tcon *tcon)
 	CIFSSMBQFSAttributeInfo(xid, tcon);
 }
 
+int
+cifs_is_path_accessible(const int xid, struct cifs_tcon *tcon,
+			struct cifs_sb_info *cifs_sb, const char *full_path)
+{
+	int rc;
+	FILE_ALL_INFO *file_info;
+
+	file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+	if (file_info == NULL)
+		return -ENOMEM;
+
+	rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info,
+			      0 /* not legacy */, cifs_sb->local_nls,
+			      cifs_sb->mnt_cifs_flags &
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
+
+	if (rc == -EOPNOTSUPP || rc == -EINVAL)
+		rc = SMBQueryInformation(xid, tcon, full_path, file_info,
+				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+				  CIFS_MOUNT_MAP_SPECIAL_CHR);
+	kfree(file_info);
+	return rc;
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -454,6 +478,7 @@ struct smb_version_operations smb1_operations = {
 	.tree_disconnect = CIFSSMBTDis,
 	.get_dfs_refer = cifs_get_dfs_refer,
 	.qfs_tcon = cifs_qfs_tcon,
+	.is_path_accessible = cifs_is_path_accessible,
 };
 
 struct smb_version_values smb1_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 14/22] CIFS: Add SMB2 support for is_path_accessible
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (11 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 13/22] CIFS: Move is_path_accessible " Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 15/22] CIFS: Move query inode info code to ops struct Pavel Shilovsky
                     ` (7 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

that needs for a successful mount through SMB2 protocol.

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/cifs_unicode.c |   61 +++++++++++++++++
 fs/cifs/cifs_unicode.h |    5 ++
 fs/cifs/smb2misc.c     |   25 +++++++
 fs/cifs/smb2ops.c      |   25 +++++++
 fs/cifs/smb2pdu.c      |  130 +++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.h      |  167 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2proto.h    |    8 ++
 7 files changed, 421 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 97c1d42..7dab9c0 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -330,3 +330,64 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
 ctoUTF16_out:
 	return i;
 }
+
+#ifdef CONFIG_CIFS_SMB2
+/*
+ * cifs_local_to_utf16_bytes - how long will a string be after conversion?
+ * @from - pointer to input string
+ * @maxbytes - don't go past this many bytes of input string
+ * @codepage - source codepage
+ *
+ * Walk a string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
+ */
+
+static int
+cifs_local_to_utf16_bytes(const char *from, int len,
+			  const struct nls_table *codepage)
+{
+	int charlen;
+	int i;
+	wchar_t wchar_to;
+
+	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
+		charlen = codepage->char2uni(from, len, &wchar_to);
+		/* Failed conversion defaults to a question mark */
+		if (charlen < 1)
+			charlen = 1;
+	}
+	return 2 * i; /* UTF16 characters are two bytes */
+}
+
+/*
+ * cifs_strndup_to_utf16 - copy a string to wire format from the local codepage
+ * @src - source string
+ * @maxlen - don't walk past this many bytes in the source string
+ * @utf16_len - the length of the allocated string in bytes (including null)
+ * @cp - source codepage
+ * @remap - map special chars
+ *
+ * Take a string convert it from the local codepage to UTF16 and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ */
+__le16 *
+cifs_strndup_to_utf16(const char *src, const int maxlen, int *utf16_len,
+		      const struct nls_table *cp, int remap)
+{
+	int len;
+	__le16 *dst;
+
+	len = cifs_local_to_utf16_bytes(src, maxlen, cp);
+	len += 2; /* NULL */
+	dst = kmalloc(len, GFP_KERNEL);
+	if (!dst) {
+		*utf16_len = 0;
+		return NULL;
+	}
+	cifsConvertToUTF16(dst, src, strlen(src), cp, remap);
+	*utf16_len = len;
+	return dst;
+}
+#endif /* CONFIG_CIFS_SMB2 */
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index a44c6eb..4fb0974 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -84,6 +84,11 @@ char *cifs_strndup_from_utf16(const char *src, const int maxlen,
 			      const struct nls_table *codepage);
 extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
 			      const struct nls_table *cp, int mapChars);
+#ifdef CONFIG_CIFS_SMB2
+extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
+				     int *utf16_len, const struct nls_table *cp,
+				     int remap);
+#endif /* CONFIG_CIFS_SMB2 */
 #endif
 
 /*
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index b690852..2c061fd 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -229,6 +229,11 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 		    ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
 		break;
 	case SMB2_CREATE:
+		*off = le32_to_cpu(
+		    ((struct smb2_create_rsp *)hdr)->CreateContextsOffset);
+		*len = le32_to_cpu(
+		    ((struct smb2_create_rsp *)hdr)->CreateContextsLength);
+		break;
 	case SMB2_READ:
 	case SMB2_QUERY_INFO:
 	case SMB2_QUERY_DIRECTORY:
@@ -312,3 +317,23 @@ calc_size_exit:
 	cFYI(1, "smb2 len %d", len);
 	return len;
 }
+
+/* Note: caller must free return buffer */
+__le16 *
+cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
+{
+	int len;
+	const char *start_of_path;
+	__le16 *to;
+
+	/* Windows doesn't allow paths beginning with \ */
+	if (from[0] == '\\')
+		start_of_path = from + 1;
+	else
+		start_of_path = from;
+	to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
+				   cifs_sb->local_nls,
+				   cifs_sb->mnt_cifs_flags &
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
+	return to;
+}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index a904b35..75904b7 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -156,6 +156,30 @@ smb2_negotiate(const int xid, struct cifs_ses *ses)
 	return rc;
 }
 
+static int
+smb2_is_path_accessible(const int xid, struct cifs_tcon *tcon,
+			struct cifs_sb_info *cifs_sb, const char *full_path)
+{
+	int rc;
+	__u64 persistent_fid, volatile_fid;
+	__le16 *utf16_path;
+
+	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+	if (!utf16_path)
+		return -ENOMEM;
+
+	rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
+		       FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0);
+	if (rc) {
+		kfree(utf16_path);
+		return rc;
+	}
+
+	rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid);
+	kfree(utf16_path);
+	return rc;
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -173,6 +197,7 @@ struct smb_version_operations smb21_operations = {
 	.logoff = SMB2_logoff,
 	.tree_connect = SMB2_tcon,
 	.tree_disconnect = SMB2_tdis,
+	.is_path_accessible = smb2_is_path_accessible,
 };
 
 struct smb_version_values smb21_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 9ec0bfe..e56ea77 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -839,3 +839,133 @@ SMB2_tdis(const int xid, struct cifs_tcon *tcon)
 
 	return rc;
 }
+
+int SMB2_open(const int xid, struct cifs_tcon *tcon, __le16 *path,
+	      u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access,
+	      __u32 create_disposition, __u32 file_attributes,
+	      __u32 create_options)
+{
+	struct smb2_create_req *pSMB2;
+	struct smb2_create_rsp *pSMB2r;
+	struct TCP_Server_Info *server;
+	struct cifs_ses *ses = tcon->ses;
+	struct kvec iov[2];
+	int resp_buftype;
+	int uni_path_len;
+	int rc = 0;
+	int num_iovecs = 2;
+
+	cFYI(1, "create/open");
+
+	if (ses && (ses->server))
+		server = ses->server;
+	else
+		return -EIO;
+
+	rc = small_smb2_init(SMB2_CREATE, tcon, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	if (enable_oplocks)
+		pSMB2->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_BATCH;
+	else
+		pSMB2->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
+	pSMB2->ImpersonationLevel = IL_IMPERSONATION;
+	pSMB2->DesiredAccess = cpu_to_le32(desired_access);
+	/* File attributes ignored on open (used in create though) */
+	pSMB2->FileAttributes = cpu_to_le32(file_attributes);
+	pSMB2->ShareAccess = FILE_SHARE_ALL_LE;
+	pSMB2->CreateDisposition = cpu_to_le32(create_disposition);
+	pSMB2->CreateOptions = cpu_to_le32(create_options);
+	uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
+	pSMB2->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)
+			- 1 /* pad */ - 4 /* do not count rfc1001 len field */);
+
+	iov[0].iov_base = (char *)pSMB2;
+
+	/* rfc1001 length field is 4 bytes so added below */
+	iov[0].iov_len = be32_to_cpu(pSMB2->hdr.smb2_buf_length) + 4;
+
+	/* MUST set path len (NameLength) to 0 opening root of share */
+	if (uni_path_len >= 4) {
+		pSMB2->NameLength = cpu_to_le16(uni_path_len - 2);
+		/* -1 since last byte is buf[0] which is sent below (path) */
+		iov[0].iov_len--;
+		iov[1].iov_len = uni_path_len;
+		iov[1].iov_base = path;
+	/* -1 since last byte is buf[0] which was counted in smb2_buf_len */
+		pSMB2->hdr.smb2_buf_length = cpu_to_be32(be32_to_cpu(
+				pSMB2->hdr.smb2_buf_length) + uni_path_len - 1);
+	} else {
+		num_iovecs = 1;
+		pSMB2->NameLength = 0;
+	}
+
+	rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
+	pSMB2r = (struct smb2_create_rsp *)iov[0].iov_base;
+
+	if (rc != 0) {
+		cifs_stats_fail_inc(tcon, SMB2CREATE);
+		goto creat_exit;
+	}
+
+	if (pSMB2r == NULL) {
+		rc = -EIO;
+		goto creat_exit;
+	}
+	*persistent_fid = pSMB2r->PersistentFileId;
+	*volatile_fid = pSMB2r->VolatileFileId;
+creat_exit:
+	free_rsp_buf(resp_buftype, pSMB2r);
+	return rc;
+}
+
+int SMB2_close(const int xid, struct cifs_tcon *tcon,
+	       u64 persistent_file_id, u64 volatile_file_id)
+{
+	struct smb2_close_req *pSMB2;
+	struct smb2_close_rsp *pSMB2r;
+	struct TCP_Server_Info *server;
+	struct cifs_ses *ses = tcon->ses;
+	struct kvec iov[1];
+	int resp_buftype;
+	int rc = 0;
+
+	cFYI(1, "Close");
+
+	if (ses && (ses->server))
+		server = ses->server;
+	else
+		return -EIO;
+
+	rc = small_smb2_init(SMB2_CLOSE, tcon, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	pSMB2->PersistentFileId = persistent_file_id;
+	pSMB2->VolatileFileId = volatile_file_id;
+
+	iov[0].iov_base = (char *)pSMB2;
+	iov[0].iov_len = be32_to_cpu(pSMB2->hdr.smb2_buf_length)
+					+ 4 /* rfc1001 len */;
+
+	rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
+	pSMB2r = (struct smb2_close_rsp *)iov[0].iov_base;
+
+	if (rc != 0) {
+		if (tcon)
+			cifs_stats_fail_inc(tcon, SMB2CLOSE);
+		goto close_exit;
+	}
+
+	if (pSMB2r == NULL) {
+		rc = -EIO;
+		goto close_exit;
+	}
+
+	/* BB FIXME - decode close response, update inode for caching */
+
+close_exit:
+	free_rsp_buf(resp_buftype, pSMB2r);
+	return rc;
+}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 007de36..6101ba2 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -275,4 +275,171 @@ struct smb2_tree_disconnect_rsp {
 	__le16 Reserved;
 } __packed;
 
+/* File Attrubutes */
+#define FILE_ATTRIBUTE_READONLY			0x00000001
+#define FILE_ATTRIBUTE_HIDDEN			0x00000002
+#define FILE_ATTRIBUTE_SYSTEM			0x00000004
+#define FILE_ATTRIBUTE_DIRECTORY		0x00000010
+#define FILE_ATTRIBUTE_ARCHIVE			0x00000020
+#define FILE_ATTRIBUTE_NORMAL			0x00000080
+#define FILE_ATTRIBUTE_TEMPORARY		0x00000100
+#define FILE_ATTRIBUTE_SPARSE_FILE		0x00000200
+#define FILE_ATTRIBUTE_REPARSE_POINT		0x00000400
+#define FILE_ATTRIBUTE_COMPRESSED		0x00000800
+#define FILE_ATTRIBUTE_OFFLINE			0x00001000
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED	0x00002000
+#define FILE_ATTRIBUTE_ENCRYPTED		0x00004000
+
+/* Oplock levels */
+#define SMB2_OPLOCK_LEVEL_NONE		0x00
+#define SMB2_OPLOCK_LEVEL_II		0x01
+#define SMB2_OPLOCK_LEVEL_EXCLUSIVE	0x08
+#define SMB2_OPLOCK_LEVEL_BATCH		0x09
+#define SMB2_OPLOCK_LEVEL_LEASE		0xFF
+
+/* Desired Access Flags */
+#define FILE_READ_DATA_LE		cpu_to_le32(0x00000001)
+#define FILE_WRITE_DATA_LE		cpu_to_le32(0x00000002)
+#define FILE_APPEND_DATA_LE		cpu_to_le32(0x00000004)
+#define FILE_READ_EA_LE			cpu_to_le32(0x00000008)
+#define FILE_WRITE_EA_LE		cpu_to_le32(0x00000010)
+#define FILE_EXECUTE_LE			cpu_to_le32(0x00000020)
+#define FILE_READ_ATTRIBUTES_LE		cpu_to_le32(0x00000080)
+#define FILE_WRITE_ATTRIBUTES_LE	cpu_to_le32(0x00000100)
+#define FILE_DELETE_LE			cpu_to_le32(0x00010000)
+#define FILE_READ_CONTROL_LE		cpu_to_le32(0x00020000)
+#define FILE_WRITE_DAC_LE		cpu_to_le32(0x00040000)
+#define FILE_WRITE_OWNER_LE		cpu_to_le32(0x00080000)
+#define FILE_SYNCHRONIZE_LE		cpu_to_le32(0x00100000)
+#define FILE_ACCESS_SYSTEM_SECURITY_LE	cpu_to_le32(0x01000000)
+#define FILE_MAXIMAL_ACCESS_LE		cpu_to_le32(0x02000000)
+#define FILE_GENERIC_ALL_LE		cpu_to_le32(0x10000000)
+#define FILE_GENERIC_EXECUTE_LE		cpu_to_le32(0x20000000)
+#define FILE_GENERIC_WRITE_LE		cpu_to_le32(0x40000000)
+#define FILE_GENERIC_READ_LE		cpu_to_le32(0x80000000)
+
+/* ShareAccess Flags */
+#define FILE_SHARE_READ_LE		cpu_to_le32(0x00000001)
+#define FILE_SHARE_WRITE_LE		cpu_to_le32(0x00000002)
+#define FILE_SHARE_DELETE_LE		cpu_to_le32(0x00000004)
+#define FILE_SHARE_ALL_LE		cpu_to_le32(0x00000007)
+
+/* CreateDisposition Flags */
+#define FILE_SUPERSEDE_LE		cpu_to_le32(0x00000000)
+#define FILE_OPEN_LE			cpu_to_le32(0x00000001)
+#define FILE_CREATE_LE			cpu_to_le32(0x00000002)
+#define	FILE_OPEN_IF_LE			cpu_to_le32(0x00000003)
+#define FILE_OVERWRITE_LE		cpu_to_le32(0x00000004)
+#define FILE_OVERWRITE_IF_LE		cpu_to_le32(0x00000005)
+
+/* CreateOptions Flags */
+#define FILE_DIRECTORY_FILE_LE		cpu_to_le32(0x00000001)
+/* same as #define CREATE_NOT_FILE_LE	cpu_to_le32(0x00000001) */
+#define FILE_WRITE_THROUGH_LE		cpu_to_le32(0x00000002)
+#define FILE_SEQUENTIAL_ONLY_LE		cpu_to_le32(0x00000004)
+#define FILE_NO_INTERMEDIATE_BUFFERRING_LE cpu_to_le32(0x00000008)
+#define FILE_SYNCHRONOUS_IO_ALERT_LE	cpu_to_le32(0x00000010)
+#define FILE_SYNCHRONOUS_IO_NON_ALERT_LE	cpu_to_le32(0x00000020)
+#define FILE_NON_DIRECTORY_FILE_LE	cpu_to_le32(0x00000040)
+#define FILE_COMPLETE_IF_OPLOCKED_LE	cpu_to_le32(0x00000100)
+#define FILE_NO_EA_KNOWLEDGE_LE		cpu_to_le32(0x00000200)
+#define FILE_RANDOM_ACCESS_LE		cpu_to_le32(0x00000800)
+#define FILE_DELETE_ON_CLOSE_LE		cpu_to_le32(0x00001000)
+#define FILE_OPEN_BY_FILE_ID_LE		cpu_to_le32(0x00002000)
+#define FILE_OPEN_FOR_BACKUP_INTENT_LE	cpu_to_le32(0x00004000)
+#define FILE_NO_COMPRESSION_LE		cpu_to_le32(0x00008000)
+#define FILE_RESERVE_OPFILTER_LE	cpu_to_le32(0x00100000)
+#define FILE_OPEN_REPARSE_POINT_LE	cpu_to_le32(0x00200000)
+#define FILE_OPEN_NO_RECALL_LE		cpu_to_le32(0x00400000)
+#define FILE_OPEN_FOR_FREE_SPACE_QUERY_LE cpu_to_le32(0x00800000)
+
+#define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \
+			| FILE_READ_ATTRIBUTES_LE)
+#define FILE_WRITE_RIGHTS_LE (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE \
+			| FILE_WRITE_EA_LE | FILE_WRITE_ATTRIBUTES_LE)
+#define FILE_EXEC_RIGHTS_LE (FILE_EXECUTE_LE)
+
+/* Impersonation Levels */
+#define IL_ANONYMOUS		cpu_to_le32(0x00000000)
+#define IL_IDENTIFICATION	cpu_to_le32(0x00000001)
+#define IL_IMPERSONATION	cpu_to_le32(0x00000002)
+#define IL_DELEGATE		cpu_to_le32(0x00000003)
+
+/* Create Context Values */
+#define SMB2_CREATE_EA_BUFFER			"ExtA" /* extended attributes */
+#define SMB2_CREATE_SD_BUFFER			"SecD" /* security descriptor */
+#define SMB2_CREATE_DURABLE_HANDLE_REQUEST	"DHnQ"
+#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT	"DHnC"
+#define SMB2_CREATE_ALLOCATION_SIZE		"AlSi"
+#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
+#define SMB2_CREATE_TIMEWARP_REQUEST		"TWrp"
+#define SMB2_CREATE_QUERY_ON_DISK_ID		"QFid"
+#define SMB2_CREATE_REQUEST_LEASE		"RqLs"
+
+struct smb2_create_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 57 */
+	__u8   SecurityFlags;
+	__u8   RequestedOplockLevel;
+	__le32 ImpersonationLevel;
+	__le64 SmbCreateFlags;
+	__le64 Reserved;
+	__le32 DesiredAccess;
+	__le32 FileAttributes;
+	__le32 ShareAccess;
+	__le32 CreateDisposition;
+	__le32 CreateOptions;
+	__le16 NameOffset;
+	__le16 NameLength;
+	__le32 CreateContextsOffset;
+	__le32 CreateContextsLength;
+	__u8   Buffer[1];
+} __packed;
+
+struct smb2_create_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 89 */
+	__u8   OplockLevel;
+	__u8   Reserved;
+	__le32 CreateAction;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 AllocationSize;
+	__le64 EndofFile;
+	__le32 FileAttributes;
+	__le32 Reserved2;
+	__u64  PersistentFileId; /* opaque endianness */
+	__u64  VolatileFileId; /* opaque endianness */
+	__le32 CreateContextsOffset;
+	__le32 CreateContextsLength;
+	__u8   Buffer[1];
+} __packed;
+
+/* Currently defined values for close flags */
+#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB	cpu_to_le16(0x0001)
+struct smb2_close_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize;	/* Must be 24 */
+	__le16 Flags;
+	__le32 Reserved;
+	__u64  PersistentFileId; /* opaque endianness */
+	__u64  VolatileFileId; /* opaque endianness */
+} __packed;
+
+struct smb2_close_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize; /* 60 */
+	__le16 Flags;
+	__le32 Reserved;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 AllocationSize;	/* Beginning of FILE_STANDARD_INFO equivalent */
+	__le64 EndOfFile;
+	__le32 Attributes;
+} __packed;
+
 #endif				/* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 0d51482..5ffc5ec 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -36,6 +36,8 @@ extern int map_smb2_to_linux_error(char *buf, bool log_err);
 extern int smb2_check_message(char *buf, unsigned int length);
 extern unsigned int smb2_calc_size(struct smb2_hdr *hdr);
 extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
+extern __le16 *cifs_convert_path_to_utf16(const char *from,
+					  struct cifs_sb_info *cifs_sb);
 
 extern int smb2_check_receive(struct mid_q_entry *mid,
 			      struct TCP_Server_Info *server, bool log_error);
@@ -54,5 +56,11 @@ extern int SMB2_tcon(const int xid, struct cifs_ses *ses,
 		     const char *tree, struct cifs_tcon *tcon,
 		     const struct nls_table *);
 extern int SMB2_tdis(const int xid, struct cifs_tcon *tcon);
+extern int SMB2_open(const int xid, struct cifs_tcon *tcon, __le16 *path,
+		      u64 *persistent_fid, u64 *volatile_fid,
+		      __u32 desired_access, __u32 create_disposition,
+		      __u32 file_attributes, __u32 create_options);
+extern int SMB2_close(const int xid, struct cifs_tcon *tcon,
+		      u64 persistent_file_id, u64 volatile_file_id);
 
 #endif			/* _SMB2PROTO_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 15/22] CIFS: Move query inode info code to ops struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (12 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 14/22] CIFS: Add SMB2 support for is_path_accessible Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 16/22] CIFS: Query SMB2 inode info Pavel Shilovsky
                     ` (6 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h  |    9 +++++
 fs/cifs/cifsproto.h |    7 ++--
 fs/cifs/inode.c     |   92 ++++++++++++++++++++-------------------------------
 fs/cifs/smb1ops.c   |   50 +++++++++++++++++++++++++++
 4 files changed, 98 insertions(+), 60 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7f5cb14..f3a4f6e 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -163,6 +163,7 @@ struct cifsFileInfo;
 struct cifs_ses;
 struct cifs_tcon;
 struct dfs_info3_param;
+struct cifs_fattr;
 
 struct smb_version_operations {
 	int (*send_cancel)(struct TCP_Server_Info *, void *,
@@ -218,6 +219,14 @@ struct smb_version_operations {
 	/* check if a path is accessible or not */
 	int (*is_path_accessible)(const int, struct cifs_tcon *,
 				  struct cifs_sb_info *, const char *);
+	/* query path data from the server */
+	int (*query_path_info)(const int, struct cifs_tcon *,
+			       struct cifs_sb_info *, const char *,
+			       FILE_ALL_INFO *, bool *);
+	/* get server index number */
+	int (*get_srv_inum)(const int, struct cifs_tcon *,
+			    struct cifs_sb_info *, const char *,
+			    struct cifs_fattr *, FILE_ALL_INFO *);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 8b5f2a6..b152cbc 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -138,10 +138,9 @@ extern struct inode *cifs_iget(struct super_block *sb,
 			       struct cifs_fattr *fattr);
 
 extern int cifs_get_file_info(struct file *filp);
-extern int cifs_get_inode_info(struct inode **pinode,
-			const unsigned char *search_path,
-			FILE_ALL_INFO *pfile_info,
-			struct super_block *sb, int xid, const __u16 *pfid);
+extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
+			       FILE_ALL_INFO *data, struct super_block *sb,
+			       int xid, const __u16 *fid);
 extern int cifs_get_file_info_unix(struct file *filp);
 extern int cifs_get_inode_info_unix(struct inode **pinode,
 			const unsigned char *search_path,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 745da3d..8ba040d 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -600,61 +600,54 @@ cgfi_exit:
 	return rc;
 }
 
-int cifs_get_inode_info(struct inode **pinode,
-	const unsigned char *full_path, FILE_ALL_INFO *pfindData,
-	struct super_block *sb, int xid, const __u16 *pfid)
+int
+cifs_get_inode_info(struct inode **inode, const char *full_path,
+		    FILE_ALL_INFO *data, struct super_block *sb, int xid,
+		    const __u16 *fid)
 {
 	int rc = 0, tmprc;
-	struct cifs_tcon *pTcon;
+	struct cifs_tcon *tcon;
+	struct TCP_Server_Info *server;
 	struct tcon_link *tlink;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	char *buf = NULL;
-	bool adjustTZ = false;
+	bool adjust_tz = false;
 	struct cifs_fattr fattr;
 
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
 		return PTR_ERR(tlink);
-	pTcon = tlink_tcon(tlink);
+	tcon = tlink_tcon(tlink);
+	server = tcon->ses->server;
 
 	cFYI(1, "Getting info on %s", full_path);
 
-	if ((pfindData == NULL) && (*pinode != NULL)) {
-		if (CIFS_I(*pinode)->clientCanCacheRead) {
+	if ((data == NULL) && (*inode != NULL)) {
+		if (CIFS_I(*inode)->clientCanCacheRead) {
 			cFYI(1, "No need to revalidate cached inode sizes");
 			goto cgii_exit;
 		}
 	}
 
-	/* if file info not passed in then get it from server */
-	if (pfindData == NULL) {
+	/* if inode info is not passed, get it from server */
+	if (data == NULL) {
+		if (!server->ops->query_path_info) {
+			rc = -ENOSYS;
+			goto cgii_exit;
+		}
 		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
 		if (buf == NULL) {
 			rc = -ENOMEM;
 			goto cgii_exit;
 		}
-		pfindData = (FILE_ALL_INFO *)buf;
-
-		/* could do find first instead but this returns more info */
-		rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
-			      0 /* not legacy */,
-			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-				CIFS_MOUNT_MAP_SPECIAL_CHR);
-		/* BB optimize code so we do not make the above call
-		when server claims no NT SMB support and the above call
-		failed at least once - set flag in tcon or mount */
-		if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
-			rc = SMBQueryInformation(xid, pTcon, full_path,
-					pfindData, cifs_sb->local_nls,
-					cifs_sb->mnt_cifs_flags &
-					  CIFS_MOUNT_MAP_SPECIAL_CHR);
-			adjustTZ = true;
-		}
+		data = (FILE_ALL_INFO *)buf;
+		rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
+						  data, &adjust_tz);
 	}
 
 	if (!rc) {
-		cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
-				       cifs_sb, adjustTZ);
+		cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
+				       adjust_tz);
 	} else if (rc == -EREMOTE) {
 		cifs_create_dfs_fattr(&fattr, sb);
 		rc = 0;
@@ -668,28 +661,16 @@ int cifs_get_inode_info(struct inode **pinode,
 	 * Is an i_ino of zero legal? Can we use that to check if the server
 	 * supports returning inode numbers?  Are there other sanity checks we
 	 * can use to ensure that the server is really filling in that field?
-	 *
-	 * We can not use the IndexNumber field by default from Windows or
-	 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
-	 * CIFS spec claims that this value is unique within the scope of a
-	 * share, and the windows docs hint that it's actually unique
-	 * per-machine.
-	 *
-	 * There may be higher info levels that work but are there Windows
-	 * server or network appliances for which IndexNumber field is not
-	 * guaranteed unique?
 	 */
-	if (*pinode == NULL) {
+	if (*inode == NULL) {
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
-			int rc1 = 0;
-
-			rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
-					full_path, &fattr.cf_uniqueid,
-					cifs_sb->local_nls,
-					cifs_sb->mnt_cifs_flags &
-						CIFS_MOUNT_MAP_SPECIAL_CHR);
-			if (rc1 || !fattr.cf_uniqueid) {
-				cFYI(1, "GetSrvInodeNum rc %d", rc1);
+			if (server->ops->get_srv_inum)
+				tmprc = server->ops->get_srv_inum(xid, tcon,
+					cifs_sb, full_path, &fattr, data);
+			else
+				tmprc = -ENOSYS;
+			if (tmprc || !fattr.cf_uniqueid) {
+				cFYI(1, "GetSrvInodeNum rc %d", tmprc);
 				fattr.cf_uniqueid = iunique(sb, ROOT_I);
 				cifs_autodisable_serverino(cifs_sb);
 			}
@@ -697,7 +678,7 @@ int cifs_get_inode_info(struct inode **pinode,
 			fattr.cf_uniqueid = iunique(sb, ROOT_I);
 		}
 	} else {
-		fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
+		fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
 	}
 
 	/* query for SFU type info if supported and needed */
@@ -711,8 +692,7 @@ int cifs_get_inode_info(struct inode **pinode,
 #ifdef CONFIG_CIFS_ACL
 	/* fill in 0777 bits from ACL */
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
-						pfid);
+		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
 		if (rc) {
 			cFYI(1, "%s: Getting ACL failed with error: %d",
 				__func__, rc);
@@ -732,12 +712,12 @@ int cifs_get_inode_info(struct inode **pinode,
 			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
 	}
 
-	if (!*pinode) {
-		*pinode = cifs_iget(sb, &fattr);
-		if (!*pinode)
+	if (!*inode) {
+		*inode = cifs_iget(sb, &fattr);
+		if (!*inode)
 			rc = -ENOMEM;
 	} else {
-		cifs_fattr_to_inode(*pinode, &fattr);
+		cifs_fattr_to_inode(*inode, &fattr);
 	}
 
 cgii_exit:
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 554ecba..670fb62 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -452,6 +452,54 @@ cifs_is_path_accessible(const int xid, struct cifs_tcon *tcon,
 	return rc;
 }
 
+static int
+cifs_query_path_info(const int xid, struct cifs_tcon *tcon,
+		     struct cifs_sb_info *cifs_sb, const char *full_path,
+		     FILE_ALL_INFO *data, bool *adjustTZ)
+{
+	int rc;
+
+	/* could do find first instead but this returns more info */
+	rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */,
+			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+	/*
+	 * BB optimize code so we do not make the above call when server claims
+	 * no NT SMB support and the above call failed at least once - set flag
+	 * in tcon or mount.
+	 */
+	if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
+		rc = SMBQueryInformation(xid, tcon, full_path, data,
+					 cifs_sb->local_nls,
+					 cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+		*adjustTZ = true;
+	}
+	return rc;
+}
+
+static int
+cifs_get_srv_inum(const int xid, struct cifs_tcon *tcon,
+		  struct cifs_sb_info *cifs_sb, const char *full_path,
+		  struct cifs_fattr *fattr, FILE_ALL_INFO *data)
+{
+	/*
+	 * We can not use the IndexNumber field by default from Windows or
+	 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
+	 * CIFS spec claims that this value is unique within the scope of a
+	 * share, and the windows docs hint that it's actually unique
+	 * per-machine.
+	 *
+	 * There may be higher info levels that work but are there Windows
+	 * server or network appliances for which IndexNumber field is not
+	 * guaranteed unique?
+	 */
+	return CIFSGetSrvInodeNumber(xid, tcon, full_path, &fattr->cf_uniqueid,
+				     cifs_sb->local_nls,
+				     cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -479,6 +527,8 @@ struct smb_version_operations smb1_operations = {
 	.get_dfs_refer = cifs_get_dfs_refer,
 	.qfs_tcon = cifs_qfs_tcon,
 	.is_path_accessible = cifs_is_path_accessible,
+	.query_path_info = cifs_query_path_info,
+	.get_srv_inum = cifs_get_srv_inum,
 };
 
 struct smb_version_values smb1_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 16/22] CIFS: Query SMB2 inode info
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (13 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 15/22] CIFS: Move query inode info code to ops struct Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 17/22] CIFS: Move building path to root to ops struct Pavel Shilovsky
                     ` (5 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
---
 fs/cifs/Makefile    |    2 +-
 fs/cifs/smb2glob.h  |   44 ++++++++++++++++++
 fs/cifs/smb2inode.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2misc.c  |    7 +++-
 fs/cifs/smb2ops.c   |   11 +++++
 fs/cifs/smb2pdu.c   |  110 +++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.h   |  111 +++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2proto.h |    7 +++
 8 files changed, 414 insertions(+), 2 deletions(-)
 create mode 100644 fs/cifs/smb2glob.h
 create mode 100644 fs/cifs/smb2inode.c

diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index daf6837..feee943 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -17,4 +17,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
 cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
 
 cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o \
-			    smb2misc.o smb2pdu.o
+			    smb2misc.o smb2pdu.o smb2inode.o
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
new file mode 100644
index 0000000..33c1d89
--- /dev/null
+++ b/fs/cifs/smb2glob.h
@@ -0,0 +1,44 @@
+/*
+ *   fs/cifs/smb2glob.h
+ *
+ *   Definitions for various global variables and structures
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002, 2011
+ *                 Etersoft, 2012
+ *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
+ *              Jeremy Allison (jra-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org)
+ *              Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2012
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ */
+#ifndef _SMB2_GLOB_H
+#define _SMB2_GLOB_H
+
+/*
+ *****************************************************************
+ * Constants go here
+ *****************************************************************
+ */
+
+/*
+ * Identifiers for functions that use the open, operation, close pattern
+ * in smb2inode.c:smb2_open_op_close()
+ */
+#define SMB2_OP_SET_DELETE 1
+#define SMB2_OP_SET_INFO 2
+#define SMB2_OP_QUERY_INFO 3
+#define SMB2_OP_QUERY_DIR 4
+#define SMB2_OP_MKDIR 5
+#define SMB2_OP_RENAME 6
+#define SMB2_OP_DELETE 7
+
+#endif	/* _SMB2_GLOB_H */
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
new file mode 100644
index 0000000..773a76d
--- /dev/null
+++ b/fs/cifs/smb2inode.c
@@ -0,0 +1,124 @@
+/*
+ *   fs/cifs/smb2inode.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002, 2011
+ *                 Etersoft, 2012
+ *   Author(s): Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org),
+ *              Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "fscache.h"
+#include "smb2glob.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+
+static int
+smb2_open_op_close(const int xid, struct cifs_tcon *tcon,
+		   struct cifs_sb_info *cifs_sb, const char *full_path,
+		   __u32 desired_access, __u32 create_disposition,
+		   __u32 file_attributes, __u32 create_options,
+		   void *data, int command)
+{
+	int rc, tmprc = 0;
+	u64 persist_fid, volatile_fid;
+	__le16 *utf16_path;
+
+	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+	if (!utf16_path)
+		return -ENOMEM;
+
+	rc = SMB2_open(xid, tcon, utf16_path, &persist_fid, &volatile_fid,
+		       desired_access, create_disposition, file_attributes,
+		       create_options);
+	if (rc) {
+		kfree(utf16_path);
+		return rc;
+	}
+
+	switch (command) {
+	case SMB2_OP_DELETE:
+		break;
+	case SMB2_OP_QUERY_INFO:
+		tmprc = SMB2_query_info(xid, tcon, persist_fid,
+					volatile_fid,
+					(struct smb2_file_all_info *)data);
+		break;
+	case SMB2_OP_MKDIR:
+		/*
+		 * Directories are created through parameters in the
+		 * SMB2_open() call.
+		 */
+		break;
+	default:
+		cERROR(1, "Invalid command");
+		break;
+	}
+
+	rc = SMB2_close(xid, tcon, persist_fid, volatile_fid);
+	if (tmprc)
+		rc = tmprc;
+	kfree(utf16_path);
+	return rc;
+}
+
+static void
+move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
+{
+	memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src);
+	dst->CurrentByteOffset = src->CurrentByteOffset;
+	dst->Mode = src->Mode;
+	dst->AlignmentRequirement = src->AlignmentRequirement;
+	dst->IndexNumber1 = 0; /* we don't use it */
+}
+
+int
+smb2_query_path_info(const int xid, struct cifs_tcon *tcon,
+		     struct cifs_sb_info *cifs_sb, const char *full_path,
+		     FILE_ALL_INFO *data, bool *adjust_tz)
+{
+	int rc;
+	struct smb2_file_all_info *smb2_data;
+
+	*adjust_tz = false;
+
+	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+			    GFP_KERNEL);
+	if (smb2_data == NULL)
+		return -ENOMEM;
+
+	rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
+				FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0,
+				smb2_data, SMB2_OP_QUERY_INFO);
+	if (rc)
+		goto out;
+
+	move_smb2_info_to_cifs(data, smb2_data);
+out:
+	kfree(smb2_data);
+	return rc;
+}
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 2c061fd..ccafe2f 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -234,8 +234,13 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 		*len = le32_to_cpu(
 		    ((struct smb2_create_rsp *)hdr)->CreateContextsLength);
 		break;
-	case SMB2_READ:
 	case SMB2_QUERY_INFO:
+		*off = le16_to_cpu(
+		    ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset);
+		*len = le32_to_cpu(
+		    ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength);
+		break;
+	case SMB2_READ:
 	case SMB2_QUERY_DIRECTORY:
 	case SMB2_IOCTL:
 	case SMB2_CHANGE_NOTIFY:
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 75904b7..709d508 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -180,6 +180,15 @@ smb2_is_path_accessible(const int xid, struct cifs_tcon *tcon,
 	return rc;
 }
 
+static int
+smb2_get_srv_inum(const int xid, struct cifs_tcon *tcon,
+		  struct cifs_sb_info *cifs_sb, const char *full_path,
+		  struct cifs_fattr *fattr, FILE_ALL_INFO *data)
+{
+	fattr->cf_uniqueid = data->IndexNumber;
+	return 0;
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -198,6 +207,8 @@ struct smb_version_operations smb21_operations = {
 	.tree_connect = SMB2_tcon,
 	.tree_disconnect = SMB2_tdis,
 	.is_path_accessible = smb2_is_path_accessible,
+	.query_path_info = smb2_query_path_info,
+	.get_srv_inum = smb2_get_srv_inum,
 };
 
 struct smb_version_values smb21_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index e56ea77..99945e1 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -969,3 +969,113 @@ close_exit:
 	free_rsp_buf(resp_buftype, pSMB2r);
 	return rc;
 }
+
+static int
+validate_buf(unsigned int offset, unsigned int buffer_length,
+	     struct smb2_hdr *hdr, unsigned int min_buf_size)
+
+{
+	unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length);
+	char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr;
+	char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
+	char *end_of_buf = begin_of_buf + buffer_length;
+
+
+	if (buffer_length < min_buf_size) {
+		cERROR(1, "buffer length %d smaller than minimum size %d",
+			   buffer_length, min_buf_size);
+		return -EINVAL;
+	}
+
+	/* check if beyond RFC1001 maximum length */
+	if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
+		cERROR(1, "buffer length %d or smb length %d too large",
+			   buffer_length, smb_len);
+		return -EINVAL;
+	}
+
+	if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
+		cERROR(1, "illegal server response, bad offset to data");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * If SMB buffer fields are valid, copy into temporary buffer to hold result.
+ * Caller must free buffer.
+ */
+static int
+validate_and_copy_buf(unsigned int offset, unsigned int buffer_length,
+		      struct smb2_hdr *hdr, unsigned int minbufsize,
+		      char *data)
+
+{
+	char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
+	int rc;
+
+	if (!data)
+		return -EINVAL;
+
+	rc = validate_buf(offset, buffer_length, hdr, minbufsize);
+	if (rc)
+		return rc;
+
+	memcpy(data, begin_of_buf, buffer_length);
+
+	return 0;
+}
+
+int SMB2_query_info(const int xid, struct cifs_tcon *tcon,
+		    u64 persistent_fid, u64 volatile_fid,
+		    struct smb2_file_all_info *data)
+{
+	struct smb2_query_info_req *pSMB2;
+	struct smb2_query_info_rsp *pSMB2r = NULL;
+	struct kvec iov[2];
+	int rc = 0;
+	int resp_buftype;
+	struct TCP_Server_Info *server;
+	struct cifs_ses *ses = tcon->ses;
+
+	cFYI(1, "Query Info");
+
+	if (ses && (ses->server))
+		server = ses->server;
+	else
+		return -EIO;
+
+	rc = small_smb2_init(SMB2_QUERY_INFO, tcon, (void **) &pSMB2);
+	if (rc)
+		return rc;
+
+	pSMB2->InfoType = SMB2_O_INFO_FILE;
+	pSMB2->FileInfoClass = FILE_ALL_INFORMATION;
+	pSMB2->PersistentFileId = persistent_fid;
+	pSMB2->VolatileFileId = volatile_fid;
+	pSMB2->InputBufferOffset =
+		cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4);
+	pSMB2->OutputBufferLength =
+		cpu_to_le32(sizeof(struct smb2_file_all_info) + MAX_NAME * 2);
+
+	iov[0].iov_base = (char *)pSMB2;
+	iov[0].iov_len = be32_to_cpu(pSMB2->hdr.smb2_buf_length) + 4;
+
+	rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
+	if (rc) {
+		cifs_stats_fail_inc(tcon, SMB2QUERY_INFO);
+		goto qinf_exit;
+	}
+	pSMB2r = (struct smb2_query_info_rsp *)iov[0].iov_base;
+
+	rc = validate_and_copy_buf(le16_to_cpu(pSMB2r->OutputBufferOffset),
+				   le32_to_cpu(pSMB2r->OutputBufferLength),
+				   &pSMB2r->hdr,
+				   sizeof(struct smb2_file_all_info),
+				   (char *)data);
+
+qinf_exit:
+	free_rsp_buf(resp_buftype, iov[0].iov_base);
+	return rc;
+}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 6101ba2..3d16902 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -442,4 +442,115 @@ struct smb2_close_rsp {
 	__le32 Attributes;
 } __packed;
 
+/* Possible InfoType values */
+#define SMB2_O_INFO_FILE	0x01
+#define SMB2_O_INFO_FILESYSTEM	0x02
+#define SMB2_O_INFO_SECURITY	0x03
+#define SMB2_O_INFO_QUOTA	0x04
+
+struct smb2_query_info_req {
+	struct smb2_hdr hdr;
+	__le16 StructureSize; /* Must be 41 */
+	__u8   InfoType;
+	__u8   FileInfoClass;
+	__le32 OutputBufferLength;
+	__le16 InputBufferOffset;
+	__u16  Reserved;
+	__le32 InputBufferLength;
+	__le32 AdditionalInformation;
+	__le32 Flags;
+	__u64  PersistentFileId; /* opaque endianness */
+	__u64  VolatileFileId; /* opaque endianness */
+	__u8   Buffer[1];
+} __packed;
+
+struct smb2_query_info_rsp {
+	struct smb2_hdr hdr;
+	__le16 StructureSize; /* Must be 9 */
+	__le16 OutputBufferOffset;
+	__le32 OutputBufferLength;
+	__u8   Buffer[1];
+} __packed;
+
+/*
+ *	PDU infolevel structure definitions
+ *	BB consider moving to a different header
+ */
+
+/* partial list of QUERY INFO levels */
+#define FILE_DIRECTORY_INFORMATION	1
+#define FILE_FULL_DIRECTORY_INFORMATION 2
+#define FILE_BOTH_DIRECTORY_INFORMATION 3
+#define FILE_BASIC_INFORMATION		4
+#define FILE_STANDARD_INFORMATION	5
+#define FILE_INTERNAL_INFORMATION	6
+#define FILE_EA_INFORMATION	        7
+#define FILE_ACCESS_INFORMATION		8
+#define FILE_NAME_INFORMATION		9
+#define FILE_RENAME_INFORMATION		10
+#define FILE_LINK_INFORMATION		11
+#define FILE_NAMES_INFORMATION		12
+#define FILE_DISPOSITION_INFORMATION	13
+#define FILE_POSITION_INFORMATION	14
+#define FILE_FULL_EA_INFORMATION	15
+#define FILE_MODE_INFORMATION		16
+#define FILE_ALIGNMENT_INFORMATION	17
+#define FILE_ALL_INFORMATION		18
+#define FILE_ALLOCATION_INFORMATION	19
+#define FILE_END_OF_FILE_INFORMATION	20
+#define FILE_ALTERNATE_NAME_INFORMATION 21
+#define FILE_STREAM_INFORMATION		22
+#define FILE_PIPE_INFORMATION		23
+#define FILE_PIPE_LOCAL_INFORMATION	24
+#define FILE_PIPE_REMOTE_INFORMATION	25
+#define FILE_MAILSLOT_QUERY_INFORMATION 26
+#define FILE_MAILSLOT_SET_INFORMATION	27
+#define FILE_COMPRESSION_INFORMATION	28
+#define FILE_OBJECT_ID_INFORMATION	29
+/* Number 30 not defined in documents */
+#define FILE_MOVE_CLUSTER_INFORMATION	31
+#define FILE_QUOTA_INFORMATION		32
+#define FILE_REPARSE_POINT_INFORMATION	33
+#define FILE_NETWORK_OPEN_INFORMATION	34
+#define FILE_ATTRIBUTE_TAG_INFORMATION	35
+#define FILE_TRACKING_INFORMATION	36
+#define FILEID_BOTH_DIRECTORY_INFORMATION 37
+#define FILEID_FULL_DIRECTORY_INFORMATION 38
+#define FILE_VALID_DATA_LENGTH_INFORMATION 39
+#define FILE_SHORT_NAME_INFORMATION	40
+#define FILE_SFIO_RESERVE_INFORMATION	44
+#define FILE_SFIO_VOLUME_INFORMATION	45
+#define FILE_HARD_LINK_INFORMATION	46
+#define FILE_NORMALIZED_NAME_INFORMATION 48
+#define FILEID_GLOBAL_TX_DIRECTORY_INFORMATION 50
+#define FILE_STANDARD_LINK_INFORMATION	54
+
+/*
+ * This level 18, although with struct with same name is different from cifs
+ * level 0x107. Level 0x107 has an extra u64 between AccessFlags and
+ * CurrentByteOffset.
+ */
+struct smb2_file_all_info { /* data block encoding of response to level 18 */
+	__le64 CreationTime;	/* Beginning of FILE_BASIC_INFO equivalent */
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
+	__u32  Pad1;		/* End of FILE_BASIC_INFO_INFO equivalent */
+	__le64 AllocationSize;	/* Beginning of FILE_STANDARD_INFO equivalent */
+	__le64 EndOfFile;	/* size ie offset to first free byte in file */
+	__le32 NumberOfLinks;	/* hard links */
+	__u8   DeletePending;
+	__u8   Directory;
+	__u16  Pad2;		/* End of FILE_STANDARD_INFO equivalent */
+	__le64 IndexNumber;
+	__le32 EASize;
+	__le32 AccessFlags;
+	__le64 CurrentByteOffset;
+	__le32 Mode;
+	__le32 AlignmentRequirement;
+	__le32 FileNameLength;
+	char   FileName[1];
+} __packed; /* level 18 Query */
+
 #endif				/* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 5ffc5ec..af4a84e 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -44,6 +44,10 @@ extern int smb2_check_receive(struct mid_q_entry *mid,
 extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
 			      unsigned int nvec, struct mid_q_entry **ret_mid);
 
+extern int smb2_query_path_info(const int xid, struct cifs_tcon *tcon,
+				struct cifs_sb_info *cifs_sb,
+				const char *full_path, FILE_ALL_INFO *data,
+				bool *adjust_tz);
 /*
  *  SMB2 Worker functions - most of protocol specific implementation details
  *  are contained within these calls
@@ -62,5 +66,8 @@ extern int SMB2_open(const int xid, struct cifs_tcon *tcon, __le16 *path,
 		      __u32 file_attributes, __u32 create_options);
 extern int SMB2_close(const int xid, struct cifs_tcon *tcon,
 		      u64 persistent_file_id, u64 volatile_file_id);
+extern int SMB2_query_info(const int xid, struct cifs_tcon *tcon,
+			   u64 persistent_file_id, u64 volatile_file_id,
+			   struct smb2_file_all_info *data);
 
 #endif			/* _SMB2PROTO_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 17/22] CIFS: Move building path to root to ops struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (14 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 16/22] CIFS: Query SMB2 inode info Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 18/22] CIFS: Add SMB2 support for build_path_to_root Pavel Shilovsky
                     ` (4 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsfs.c    |    4 ++--
 fs/cifs/cifsglob.h  |   12 ++++++++++++
 fs/cifs/cifsproto.h |    3 ---
 fs/cifs/connect.c   |    2 +-
 fs/cifs/inode.c     |   32 --------------------------------
 fs/cifs/smb1ops.c   |   32 ++++++++++++++++++++++++++++++++
 6 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index bb4b919..965a21d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -550,8 +550,8 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
 	char *s, *p;
 	char sep;
 
-	full_path = cifs_build_path_to_root(vol, cifs_sb,
-					    cifs_sb_master_tcon(cifs_sb));
+	full_path = build_path_to_root(vol, cifs_sb,
+				       cifs_sb_master_tcon(cifs_sb));
 	if (full_path == NULL)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index f3a4f6e..d027dbf 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -164,6 +164,7 @@ struct cifs_ses;
 struct cifs_tcon;
 struct dfs_info3_param;
 struct cifs_fattr;
+struct smb_vol;
 
 struct smb_version_operations {
 	int (*send_cancel)(struct TCP_Server_Info *, void *,
@@ -227,6 +228,8 @@ struct smb_version_operations {
 	int (*get_srv_inum)(const int, struct cifs_tcon *,
 			    struct cifs_sb_info *, const char *,
 			    struct cifs_fattr *, FILE_ALL_INFO *);
+	char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *,
+				     struct cifs_tcon *);
 };
 
 struct smb_version_values {
@@ -797,6 +800,15 @@ convert_delimiter(char *path, char delim)
 	}
 }
 
+static inline char *
+build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
+		   struct cifs_tcon *tcon)
+{
+	if (!vol->ops->build_path_to_root)
+		return NULL;
+	return vol->ops->build_path_to_root(vol, cifs_sb, tcon);
+}
+
 #ifdef CONFIG_CIFS_STATS
 #define cifs_stats_inc atomic_inc
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b152cbc..34351e5 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -57,9 +57,6 @@ extern int init_cifs_idmap(void);
 extern void exit_cifs_idmap(void);
 extern void cifs_destroy_idmaptrees(void);
 extern char *build_path_from_dentry(struct dentry *);
-extern char *cifs_build_path_to_root(struct smb_vol *vol,
-				     struct cifs_sb_info *cifs_sb,
-				     struct cifs_tcon *tcon);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *cifs_compose_mount_options(const char *sb_mountdata,
 		const char *fullpath, const struct dfs_info3_param *ref,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index a1f301f..b7816fd 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3667,7 +3667,7 @@ remote_path_check:
 			goto mount_fail_check;
 		}
 		/* build_path_to_root works only when we have a valid tcon */
-		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
+		full_path = build_path_to_root(volume_info, cifs_sb, tcon);
 		if (full_path == NULL) {
 			rc = -ENOMEM;
 			goto mount_fail_check;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8ba040d..a6a5817 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -730,38 +730,6 @@ static const struct inode_operations cifs_ipc_inode_ops = {
 	.lookup = cifs_lookup,
 };
 
-char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
-			      struct cifs_tcon *tcon)
-{
-	int pplen = vol->prepath ? strlen(vol->prepath) : 0;
-	int dfsplen;
-	char *full_path = NULL;
-
-	/* if no prefix path, simply set path to the root of share to "" */
-	if (pplen == 0) {
-		full_path = kmalloc(1, GFP_KERNEL);
-		if (full_path)
-			full_path[0] = 0;
-		return full_path;
-	}
-
-	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
-		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
-	else
-		dfsplen = 0;
-
-	full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
-	if (full_path == NULL)
-		return full_path;
-
-	if (dfsplen)
-		strncpy(full_path, tcon->treeName, dfsplen);
-	strncpy(full_path + dfsplen, vol->prepath, pplen);
-	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
-	full_path[dfsplen + pplen] = 0; /* add trailing null */
-	return full_path;
-}
-
 static int
 cifs_find_inode(struct inode *inode, void *opaque)
 {
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 670fb62..f4764c0 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -500,6 +500,37 @@ cifs_get_srv_inum(const int xid, struct cifs_tcon *tcon,
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 }
 
+static char *
+cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
+			struct cifs_tcon *tcon)
+{
+	int pplen = vol->prepath ? strlen(vol->prepath) : 0;
+	int dfsplen;
+	char *full_path = NULL;
+
+	/* if no prefix path, simply set path to the root of share to "" */
+	if (pplen == 0) {
+		full_path = kzalloc(1, GFP_KERNEL);
+		return full_path;
+	}
+
+	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
+	else
+		dfsplen = 0;
+
+	full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
+	if (full_path == NULL)
+		return full_path;
+
+	if (dfsplen)
+		strncpy(full_path, tcon->treeName, dfsplen);
+	strncpy(full_path + dfsplen, vol->prepath, pplen);
+	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
+	full_path[dfsplen + pplen] = 0; /* add trailing null */
+	return full_path;
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -529,6 +560,7 @@ struct smb_version_operations smb1_operations = {
 	.is_path_accessible = cifs_is_path_accessible,
 	.query_path_info = cifs_query_path_info,
 	.get_srv_inum = cifs_get_srv_inum,
+	.build_path_to_root = cifs_build_path_to_root,
 };
 
 struct smb_version_values smb1_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 18/22] CIFS: Add SMB2 support for build_path_to_root
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (15 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 17/22] CIFS: Move building path to root to ops struct Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 19/22] CIFS: Move echo code to osp struct Pavel Shilovsky
                     ` (3 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/smb2ops.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 709d508..655a65a 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -189,6 +189,23 @@ smb2_get_srv_inum(const int xid, struct cifs_tcon *tcon,
 	return 0;
 }
 
+static char *
+smb2_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
+			struct cifs_tcon *tcon)
+{
+	int pplen = vol->prepath ? strlen(vol->prepath) : 0;
+	char *full_path = NULL;
+
+	/* if no prefix path, simply set path to the root of share to "" */
+	if (pplen == 0) {
+		full_path = kzalloc(2, GFP_KERNEL);
+		return full_path;
+	}
+
+	cERROR(1, "prefixpath is not supported for SMB2 now");
+	return NULL;
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -209,6 +226,7 @@ struct smb_version_operations smb21_operations = {
 	.is_path_accessible = smb2_is_path_accessible,
 	.query_path_info = smb2_query_path_info,
 	.get_srv_inum = smb2_get_srv_inum,
+	.build_path_to_root = smb2_build_path_to_root,
 };
 
 struct smb_version_values smb21_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 19/22] CIFS: Move echo code to osp struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (16 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 18/22] CIFS: Add SMB2 support for build_path_to_root Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 20/22] CIFS: Add echo request support for SMB2 Pavel Shilovsky
                     ` (2 subsequent siblings)
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h |    4 ++++
 fs/cifs/connect.c  |   10 ++++++----
 fs/cifs/smb1ops.c  |    1 +
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index d027dbf..860549a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -230,6 +230,10 @@ struct smb_version_operations {
 			    struct cifs_fattr *, FILE_ALL_INFO *);
 	char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *,
 				     struct cifs_tcon *);
+	/* check if we can send an echo or nor */
+	bool (*can_echo)(struct TCP_Server_Info *);
+	/* send echo request */
+	int (*echo)(struct TCP_Server_Info *);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index b7816fd..4c919bc 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -405,15 +405,17 @@ cifs_echo_request(struct work_struct *work)
 					struct TCP_Server_Info, echo.work);
 
 	/*
-	 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
-	 * done, which is indicated by maxBuf != 0. Also, no need to ping if
-	 * we got a response recently
+	 * We cannot send an echo if it is disabled or until the
+	 * NEGOTIATE_PROTOCOL request is done, which is indicated by
+	 * server->ops->need_neg() == true. Also, no need to ping if
+	 * we got a response recently.
 	 */
 	if (!server->ops->need_neg || server->ops->need_neg(server) ||
+	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
 	    time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
 		goto requeue_echo;
 
-	rc = CIFSSMBEcho(server);
+	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
 	if (rc)
 		cFYI(1, "Unable to send echo request to server: %s",
 			server->hostname);
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index f4764c0..0bbe785 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -561,6 +561,7 @@ struct smb_version_operations smb1_operations = {
 	.query_path_info = cifs_query_path_info,
 	.get_srv_inum = cifs_get_srv_inum,
 	.build_path_to_root = cifs_build_path_to_root,
+	.echo = CIFSSMBEcho,
 };
 
 struct smb_version_values smb1_values = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 20/22] CIFS: Add echo request support for SMB2
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (17 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 19/22] CIFS: Move echo code to osp struct Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 21/22] CIFS: Move clear/print_stats code to ops struct Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 22/22] CIFS: Allow SMB2 statistics to be tracked Pavel Shilovsky
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Pavel Shilovsky

From: Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Signed-off-by: Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/cifs/cifsglob.h  |    3 +++
 fs/cifs/connect.c   |    3 ---
 fs/cifs/smb2ops.c   |    8 ++++++++
 fs/cifs/smb2pdu.c   |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.h   |   12 ++++++++++++
 fs/cifs/smb2proto.h |    2 ++
 6 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 860549a..30f5bd7 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -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
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4c919bc..b4d7fd7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -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? */
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 655a65a..bf277c3 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -206,6 +206,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->echos;
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -224,6 +230,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,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 99945e1..10eb1b6 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1079,3 +1079,51 @@ qinf_exit:
 	free_rsp_buf(resp_buftype, iov[0].iov_base);
 	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 *smb2;
+	int rc = 0;
+	struct kvec iov;
+
+	cFYI(1, "In echo request");
+
+	rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&smb2);
+	if (rc)
+		return rc;
+
+	smb2->hdr.CreditRequest = cpu_to_le16(1);
+
+	iov.iov_base = smb2;
+	iov.iov_len = be32_to_cpu(smb2->hdr.smb2_buf_length) + 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(smb2);
+	return rc;
+}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 3d16902..0ebff1a 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -442,6 +442,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
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index af4a84e..cda1dab 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -43,6 +43,7 @@ extern int smb2_check_receive(struct mid_q_entry *mid,
 			      struct TCP_Server_Info *server, bool log_error);
 extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
 			      unsigned int nvec, struct mid_q_entry **ret_mid);
+extern void smb2_echo_request(struct work_struct *work);
 
 extern int smb2_query_path_info(const int xid, struct cifs_tcon *tcon,
 				struct cifs_sb_info *cifs_sb,
@@ -69,5 +70,6 @@ extern int SMB2_close(const int xid, struct cifs_tcon *tcon,
 extern int SMB2_query_info(const 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 */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 21/22] CIFS: Move clear/print_stats code to ops struct
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (18 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 20/22] CIFS: Add echo request support for SMB2 Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  2012-06-19 12:40   ` [PATCH 22/22] CIFS: Allow SMB2 statistics to be tracked Pavel Shilovsky
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifs_debug.c |   60 ++++---------------------------------------
 fs/cifs/cifsglob.h   |   48 ++++++++++++++++++++---------------
 fs/cifs/cifssmb.c    |   54 ++++++++++++++++++++--------------------
 fs/cifs/misc.c       |    2 +-
 fs/cifs/smb1ops.c    |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 129 insertions(+), 103 deletions(-)

diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 8aa8693..d9ea6ed 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -282,24 +282,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
 							  struct cifs_tcon,
 							  tcon_list);
 					atomic_set(&tcon->num_smbs_sent, 0);
-					atomic_set(&tcon->num_writes, 0);
-					atomic_set(&tcon->num_reads, 0);
-					atomic_set(&tcon->num_oplock_brks, 0);
-					atomic_set(&tcon->num_opens, 0);
-					atomic_set(&tcon->num_posixopens, 0);
-					atomic_set(&tcon->num_posixmkdirs, 0);
-					atomic_set(&tcon->num_closes, 0);
-					atomic_set(&tcon->num_deletes, 0);
-					atomic_set(&tcon->num_mkdirs, 0);
-					atomic_set(&tcon->num_rmdirs, 0);
-					atomic_set(&tcon->num_renames, 0);
-					atomic_set(&tcon->num_t2renames, 0);
-					atomic_set(&tcon->num_ffirst, 0);
-					atomic_set(&tcon->num_fnext, 0);
-					atomic_set(&tcon->num_fclose, 0);
-					atomic_set(&tcon->num_hardlinks, 0);
-					atomic_set(&tcon->num_symlinks, 0);
-					atomic_set(&tcon->num_locks, 0);
+					if (server->ops->clear_stats)
+						server->ops->clear_stats(tcon);
 				}
 			}
 		}
@@ -358,42 +342,10 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
 				seq_printf(m, "\n%d) %s", i, tcon->treeName);
 				if (tcon->need_reconnect)
 					seq_puts(m, "\tDISCONNECTED ");
-				seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
-					atomic_read(&tcon->num_smbs_sent),
-					atomic_read(&tcon->num_oplock_brks));
-				seq_printf(m, "\nReads:  %d Bytes: %lld",
-					atomic_read(&tcon->num_reads),
-					(long long)(tcon->bytes_read));
-				seq_printf(m, "\nWrites: %d Bytes: %lld",
-					atomic_read(&tcon->num_writes),
-					(long long)(tcon->bytes_written));
-				seq_printf(m, "\nFlushes: %d",
-					atomic_read(&tcon->num_flushes));
-				seq_printf(m, "\nLocks: %d HardLinks: %d "
-					      "Symlinks: %d",
-					atomic_read(&tcon->num_locks),
-					atomic_read(&tcon->num_hardlinks),
-					atomic_read(&tcon->num_symlinks));
-				seq_printf(m, "\nOpens: %d Closes: %d "
-					      "Deletes: %d",
-					atomic_read(&tcon->num_opens),
-					atomic_read(&tcon->num_closes),
-					atomic_read(&tcon->num_deletes));
-				seq_printf(m, "\nPosix Opens: %d "
-					      "Posix Mkdirs: %d",
-					atomic_read(&tcon->num_posixopens),
-					atomic_read(&tcon->num_posixmkdirs));
-				seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
-					atomic_read(&tcon->num_mkdirs),
-					atomic_read(&tcon->num_rmdirs));
-				seq_printf(m, "\nRenames: %d T2 Renames %d",
-					atomic_read(&tcon->num_renames),
-					atomic_read(&tcon->num_t2renames));
-				seq_printf(m, "\nFindFirst: %d FNext %d "
-					      "FClose %d",
-					atomic_read(&tcon->num_ffirst),
-					atomic_read(&tcon->num_fnext),
-					atomic_read(&tcon->num_fclose));
+				seq_printf(m, "\nSMBs: %d",
+					   atomic_read(&tcon->num_smbs_sent));
+				if (server->ops->print_stats)
+					server->ops->print_stats(m, tcon);
 			}
 		}
 	}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 30f5bd7..3665e1c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -194,6 +194,8 @@ struct smb_version_operations {
 	/* find mid corresponding to the response message */
 	struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
 	void (*dump_detail)(void *);
+	void (*clear_stats)(struct cifs_tcon *);
+	void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
 	/* verify the message */
 	int (*check_message)(char *, unsigned int);
 	bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
@@ -556,27 +558,31 @@ struct cifs_tcon {
 	enum statusEnum tidStatus;
 #ifdef CONFIG_CIFS_STATS
 	atomic_t num_smbs_sent;
-	atomic_t num_writes;
-	atomic_t num_reads;
-	atomic_t num_flushes;
-	atomic_t num_oplock_brks;
-	atomic_t num_opens;
-	atomic_t num_closes;
-	atomic_t num_deletes;
-	atomic_t num_mkdirs;
-	atomic_t num_posixopens;
-	atomic_t num_posixmkdirs;
-	atomic_t num_rmdirs;
-	atomic_t num_renames;
-	atomic_t num_t2renames;
-	atomic_t num_ffirst;
-	atomic_t num_fnext;
-	atomic_t num_fclose;
-	atomic_t num_hardlinks;
-	atomic_t num_symlinks;
-	atomic_t num_locks;
-	atomic_t num_acl_get;
-	atomic_t num_acl_set;
+	union {
+		struct {
+			atomic_t num_writes;
+			atomic_t num_reads;
+			atomic_t num_flushes;
+			atomic_t num_oplock_brks;
+			atomic_t num_opens;
+			atomic_t num_closes;
+			atomic_t num_deletes;
+			atomic_t num_mkdirs;
+			atomic_t num_posixopens;
+			atomic_t num_posixmkdirs;
+			atomic_t num_rmdirs;
+			atomic_t num_renames;
+			atomic_t num_t2renames;
+			atomic_t num_ffirst;
+			atomic_t num_fnext;
+			atomic_t num_fclose;
+			atomic_t num_hardlinks;
+			atomic_t num_symlinks;
+			atomic_t num_locks;
+			atomic_t num_acl_get;
+			atomic_t num_acl_set;
+		} cifs_stats;
+	} stats;
 #ifdef CONFIG_CIFS_STATS2
 	unsigned long long time_writes;
 	unsigned long long time_reads;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 13e1c7f..0fb345d 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -875,7 +875,7 @@ PsxDelete:
 		cFYI(1, "Posix delete returned %d", rc);
 	cifs_buf_release(pSMB);
 
-	cifs_stats_inc(&tcon->num_deletes);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 
 	if (rc == -EAGAIN)
 		goto PsxDelete;
@@ -917,7 +917,7 @@ DelFileRetry:
 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_deletes);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 	if (rc)
 		cFYI(1, "Error in RMFile = %d", rc);
 
@@ -961,7 +961,7 @@ RmDirRetry:
 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_rmdirs);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
 	if (rc)
 		cFYI(1, "Error in RMDir = %d", rc);
 
@@ -1004,7 +1004,7 @@ MkDirRetry:
 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_mkdirs);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
 	if (rc)
 		cFYI(1, "Error in Mkdir = %d", rc);
 
@@ -1126,9 +1126,9 @@ psx_create_err:
 	cifs_buf_release(pSMB);
 
 	if (posix_flags & SMB_O_DIRECTORY)
-		cifs_stats_inc(&tcon->num_posixmkdirs);
+		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
 	else
-		cifs_stats_inc(&tcon->num_posixopens);
+		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
 
 	if (rc == -EAGAIN)
 		goto PsxCreat;
@@ -1249,7 +1249,7 @@ OldOpenRetry:
 	/* long_op set to 1 to allow for oplock break timeouts */
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_opens);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
 	if (rc) {
 		cFYI(1, "Error in Open = %d", rc);
 	} else {
@@ -1362,7 +1362,7 @@ openRetry:
 	/* long_op set to 1 to allow for oplock break timeouts */
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_opens);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
 	if (rc) {
 		cFYI(1, "Error in Open = %d", rc);
 	} else {
@@ -1627,7 +1627,7 @@ cifs_async_readv(struct cifs_readdata *rdata)
 			     rdata, 0);
 
 	if (rc == 0)
-		cifs_stats_inc(&tcon->num_reads);
+		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
 	else
 		kref_put(&rdata->refcount, cifs_readdata_release);
 
@@ -1697,7 +1697,7 @@ CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
 			 &resp_buf_type, CIFS_LOG_ERROR);
-	cifs_stats_inc(&tcon->num_reads);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
 	pSMBr = (READ_RSP *)iov[0].iov_base;
 	if (rc) {
 		cERROR(1, "Send error in read = %d", rc);
@@ -1849,7 +1849,7 @@ CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
-	cifs_stats_inc(&tcon->num_writes);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
 	if (rc) {
 		cFYI(1, "Send error in write = %d", rc);
 	} else {
@@ -2098,7 +2098,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
 			     NULL, cifs_writev_callback, wdata, 0);
 
 	if (rc == 0)
-		cifs_stats_inc(&tcon->num_writes);
+		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
 	else
 		kref_put(&wdata->refcount, cifs_writedata_release);
 
@@ -2188,7 +2188,7 @@ CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
 
 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
 			  long_op);
-	cifs_stats_inc(&tcon->num_writes);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
 	if (rc) {
 		cFYI(1, "Send error Write2 = %d", rc);
 	} else if (resp_buf_type == 0) {
@@ -2254,7 +2254,7 @@ int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
 	iov[1].iov_base = (char *)buf;
 	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
 
-	cifs_stats_inc(&tcon->num_locks);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
 	if (rc)
 		cFYI(1, "Send error in cifs_lockv = %d", rc);
@@ -2323,7 +2323,7 @@ CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
 		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
 		/* SMB buffer freed by function above */
 	}
-	cifs_stats_inc(&tcon->num_locks);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
 	if (rc)
 		cFYI(1, "Send error in Lock = %d", rc);
 
@@ -2488,7 +2488,7 @@ CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
 	pSMB->LastWriteTime = 0xFFFFFFFF;
 	pSMB->ByteCount = 0;
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
-	cifs_stats_inc(&tcon->num_closes);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
 	if (rc) {
 		if (rc != -EINTR) {
 			/* EINTR is expected when user ctl-c to kill app */
@@ -2517,7 +2517,7 @@ CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
 	pSMB->FileID = (__u16) smb_file_id;
 	pSMB->ByteCount = 0;
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
-	cifs_stats_inc(&tcon->num_flushes);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
 	if (rc)
 		cERROR(1, "Send error in Flush = %d", rc);
 
@@ -2580,7 +2580,7 @@ renameRetry:
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_renames);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
 	if (rc)
 		cFYI(1, "Send error in rename = %d", rc);
 
@@ -2661,7 +2661,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&pTcon->num_t2renames);
+	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
 	if (rc)
 		cFYI(1, "Send error in Rename (by file handle) = %d", rc);
 
@@ -2818,7 +2818,7 @@ createSymLinkRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_symlinks);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
 	if (rc)
 		cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
 
@@ -2904,7 +2904,7 @@ createHardLinkRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_hardlinks);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
 	if (rc)
 		cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
 
@@ -2976,7 +2976,7 @@ winCreateHardLinkRetry:
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_hardlinks);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
 	if (rc)
 		cFYI(1, "Send error in hard link (NT rename) = %d", rc);
 
@@ -3394,7 +3394,7 @@ queryAclRetry:
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_acl_get);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
 	if (rc) {
 		cFYI(1, "Send error in Query POSIX ACL = %d", rc);
 	} else {
@@ -3705,7 +3705,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
 
 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
 			 0);
-	cifs_stats_inc(&tcon->num_acl_get);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
 	if (rc) {
 		cFYI(1, "Send error in QuerySecDesc = %d", rc);
 	} else {                /* decode response */
@@ -4307,7 +4307,7 @@ findFirstRetry:
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_ffirst);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
 
 	if (rc) {/* BB add logic to retry regular search if Unix search
 			rejected unexpectedly by server */
@@ -4433,7 +4433,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	cifs_stats_inc(&tcon->num_fnext);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
 	if (rc) {
 		if (rc == -EBADF) {
 			psrch_inf->endOfSearch = true;
@@ -4524,7 +4524,7 @@ CIFSFindClose(const int xid, struct cifs_tcon *tcon,
 	if (rc)
 		cERROR(1, "Send error in FindClose = %d", rc);
 
-	cifs_stats_inc(&tcon->num_fclose);
+	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
 
 	/* Since session is dead, search handle closed on server already */
 	if (rc == -EAGAIN)
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index df9f886..f090612 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -461,7 +461,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 			if (tcon->tid != buf->Tid)
 				continue;
 
-			cifs_stats_inc(&tcon->num_oplock_brks);
+			cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
 			spin_lock(&cifs_file_list_lock);
 			list_for_each(tmp2, &tcon->openFileList) {
 				netfile = list_entry(tmp2, struct cifsFileInfo,
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 0bbe785..8cec320 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -531,6 +531,72 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
 	return full_path;
 }
 
+static void
+cifs_clear_stats(struct cifs_tcon *tcon)
+{
+#ifdef CONFIG_CIFS_STATS
+	atomic_set(&tcon->stats.cifs_stats.num_writes, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_reads, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_flushes, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_oplock_brks, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_opens, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_posixopens, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_posixmkdirs, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_closes, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_deletes, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_mkdirs, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_rmdirs, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_renames, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_t2renames, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_ffirst, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_fnext, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_fclose, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_hardlinks, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_symlinks, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_locks, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_acl_get, 0);
+	atomic_set(&tcon->stats.cifs_stats.num_acl_set, 0);
+#endif
+}
+
+static void
+cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
+{
+#ifdef CONFIG_CIFS_STATS
+	seq_printf(m, " Oplocks breaks: %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_oplock_brks));
+	seq_printf(m, "\nReads:  %d Bytes: %llu",
+		   atomic_read(&tcon->stats.cifs_stats.num_reads),
+		   (long long)(tcon->bytes_read));
+	seq_printf(m, "\nWrites: %d Bytes: %llu",
+		   atomic_read(&tcon->stats.cifs_stats.num_writes),
+		   (long long)(tcon->bytes_written));
+	seq_printf(m, "\nFlushes: %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_flushes));
+	seq_printf(m, "\nLocks: %d HardLinks: %d Symlinks: %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_locks),
+		   atomic_read(&tcon->stats.cifs_stats.num_hardlinks),
+		   atomic_read(&tcon->stats.cifs_stats.num_symlinks));
+	seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_opens),
+		   atomic_read(&tcon->stats.cifs_stats.num_closes),
+		   atomic_read(&tcon->stats.cifs_stats.num_deletes));
+	seq_printf(m, "\nPosix Opens: %d Posix Mkdirs: %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_posixopens),
+		   atomic_read(&tcon->stats.cifs_stats.num_posixmkdirs));
+	seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_mkdirs),
+		   atomic_read(&tcon->stats.cifs_stats.num_rmdirs));
+	seq_printf(m, "\nRenames: %d T2 Renames %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_renames),
+		   atomic_read(&tcon->stats.cifs_stats.num_t2renames));
+	seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
+		   atomic_read(&tcon->stats.cifs_stats.num_ffirst),
+		   atomic_read(&tcon->stats.cifs_stats.num_fnext),
+		   atomic_read(&tcon->stats.cifs_stats.num_fclose));
+#endif
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -547,6 +613,8 @@ struct smb_version_operations smb1_operations = {
 	.find_mid = cifs_find_mid,
 	.check_message = checkSMB,
 	.dump_detail = cifs_dump_detail,
+	.clear_stats = cifs_clear_stats,
+	.print_stats = cifs_print_stats,
 	.is_oplock_break = is_valid_oplock_break,
 	.check_trans2 = cifs_check_trans2,
 	.need_neg = cifs_need_neg,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 22/22] CIFS: Allow SMB2 statistics to be tracked
       [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
                     ` (19 preceding siblings ...)
  2012-06-19 12:40   ` [PATCH 21/22] CIFS: Move clear/print_stats code to ops struct Pavel Shilovsky
@ 2012-06-19 12:40   ` Pavel Shilovsky
  20 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-19 12:40 UTC (permalink / raw)
  To: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Since there are only 19 command codes, it also is easier to track by exact
command code than it was for cifs.

Signed-off-by: Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
---
 fs/cifs/cifsglob.h |    9 ++++++
 fs/cifs/smb2ops.c  |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2pdu.c  |    4 +--
 3 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 3665e1c..9f11a78 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -28,6 +28,9 @@
 #include "cifsacl.h"
 #include <crypto/internal/hash.h>
 #include <linux/scatterlist.h>
+#ifdef CONFIG_CIFS_SMB2
+#include "smb2pdu.h"
+#endif
 
 /*
  * The sizes of various internal tables and strings
@@ -582,6 +585,12 @@ struct cifs_tcon {
 			atomic_t num_acl_get;
 			atomic_t num_acl_set;
 		} cifs_stats;
+#ifdef CONFIG_CIFS_SMB2
+		struct {
+			atomic_t smb2_com_sent[NUMBER_OF_SMB2_COMMANDS];
+			atomic_t smb2_com_failed[NUMBER_OF_SMB2_COMMANDS];
+		} smb2_stats;
+#endif /* CONFIG_CIFS_SMB2 */
 	} stats;
 #ifdef CONFIG_CIFS_STATS2
 	unsigned long long time_writes;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index bf277c3..e3686ee 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -212,6 +212,85 @@ smb2_can_echo(struct TCP_Server_Info *server)
 	return server->echos;
 }
 
+static void
+smb2_clear_stats(struct cifs_tcon *tcon)
+{
+#ifdef CONFIG_CIFS_STATS
+	int i;
+	for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
+		atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
+		atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
+	}
+#endif
+}
+
+static void
+smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
+{
+#ifdef CONFIG_CIFS_STATS
+	atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
+	atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
+	seq_printf(m, "\nNegotiates: %d sent %d failed",
+		   atomic_read(&sent[SMB2NEGOTIATE]),
+		   atomic_read(&failed[SMB2NEGOTIATE]));
+	seq_printf(m, "\nSessionSetups: %d sent %d failed",
+		   atomic_read(&sent[SMB2SESSION_SETUP]),
+		   atomic_read(&failed[SMB2SESSION_SETUP]));
+#define SMB2LOGOFF		0x0002 /* trivial request/resp */
+	seq_printf(m, "\nLogoffs: %d sent %d failed",
+		   atomic_read(&sent[SMB2LOGOFF]),
+		   atomic_read(&failed[SMB2LOGOFF]));
+	seq_printf(m, "\nTreeConnects: %d sent %d failed",
+		   atomic_read(&sent[SMB2TREE_CONNECT]),
+		   atomic_read(&failed[SMB2TREE_CONNECT]));
+	seq_printf(m, "\nTreeDisconnects: %d sent %d failed",
+		   atomic_read(&sent[SMB2TREE_DISCONNECT]),
+		   atomic_read(&failed[SMB2TREE_DISCONNECT]));
+	seq_printf(m, "\nCreates: %d sent %d failed",
+		   atomic_read(&sent[SMB2CREATE]),
+		   atomic_read(&failed[SMB2CREATE]));
+	seq_printf(m, "\nCloses: %d sent %d failed",
+		   atomic_read(&sent[SMB2CLOSE]),
+		   atomic_read(&failed[SMB2CLOSE]));
+	seq_printf(m, "\nFlushes: %d sent %d failed",
+		   atomic_read(&sent[SMB2FLUSH]),
+		   atomic_read(&failed[SMB2FLUSH]));
+	seq_printf(m, "\nReads: %d sent %d failed",
+		   atomic_read(&sent[SMB2READ]),
+		   atomic_read(&failed[SMB2READ]));
+	seq_printf(m, "\nWrites: %d sent %d failed",
+		   atomic_read(&sent[SMB2WRITE]),
+		   atomic_read(&failed[SMB2WRITE]));
+	seq_printf(m, "\nLocks: %d sent %d failed",
+		   atomic_read(&sent[SMB2LOCK]),
+		   atomic_read(&failed[SMB2LOCK]));
+	seq_printf(m, "\nIOCTLs: %d sent %d failed",
+		   atomic_read(&sent[SMB2IOCTL]),
+		   atomic_read(&failed[SMB2IOCTL]));
+	seq_printf(m, "\nCancels: %d sent %d failed",
+		   atomic_read(&sent[SMB2CANCEL]),
+		   atomic_read(&failed[SMB2CANCEL]));
+	seq_printf(m, "\nEchos: %d sent %d failed",
+		   atomic_read(&sent[SMB2ECHO]),
+		   atomic_read(&failed[SMB2ECHO]));
+	seq_printf(m, "\nQueryDirectories: %d sent %d failed",
+		   atomic_read(&sent[SMB2QUERY_DIRECTORY]),
+		   atomic_read(&failed[SMB2QUERY_DIRECTORY]));
+	seq_printf(m, "\nChangeNotifies: %d sent %d failed",
+		   atomic_read(&sent[SMB2CHANGE_NOTIFY]),
+		   atomic_read(&failed[SMB2CHANGE_NOTIFY]));
+	seq_printf(m, "\nQueryInfos: %d sent %d failed",
+		   atomic_read(&sent[SMB2QUERY_INFO]),
+		   atomic_read(&failed[SMB2QUERY_INFO]));
+	seq_printf(m, "\nSetInfos: %d sent %d failed",
+		   atomic_read(&sent[SMB2SET_INFO]),
+		   atomic_read(&failed[SMB2SET_INFO]));
+	seq_printf(m, "\nOplockBreaks: %d sent %d failed",
+		   atomic_read(&sent[SMB2OPLOCK_BREAK]),
+		   atomic_read(&failed[SMB2OPLOCK_BREAK]));
+#endif
+}
+
 struct smb_version_operations smb21_operations = {
 	.setup_request = smb2_setup_request,
 	.check_receive = smb2_check_receive,
@@ -223,6 +302,8 @@ struct smb_version_operations smb21_operations = {
 	.find_mid = smb2_find_mid,
 	.check_message = smb2_check_message,
 	.dump_detail = smb2_dump_detail,
+	.clear_stats = smb2_clear_stats,
+	.print_stats = smb2_print_stats,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
 	.sess_setup = SMB2_sess_setup,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 10eb1b6..609eb04 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -286,10 +286,8 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
 
 	if (tcon != NULL) {
 #ifdef CONFIG_CIFS_STATS2
-		/*
 		uint16_t com_code = le16_to_cpu(smb2_command);
 		cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
-		*/
 #endif
 		cifs_stats_inc(&tcon->num_smbs_sent);
 	}
@@ -685,7 +683,7 @@ SMB2_logoff(const int xid, struct cifs_ses *ses)
 
 static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
 {
-	/* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[code]); */
+	cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]);
 }
 
 #define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/22] CIFS: Add SMB2 status codes
       [not found]     ` <1340109611-7210-2-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2012-06-19 22:22       ` Jeff Layton
       [not found]         ` <20120619152207.6d48ec92-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
  0 siblings, 1 reply; 28+ messages in thread
From: Jeff Layton @ 2012-06-19 22:22 UTC (permalink / raw)
  To: Pavel Shilovsky; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Tue, 19 Jun 2012 16:39:50 +0400
Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:

> +#define STATUS_GUARD_PAGE_VIOLATION	 0x80000001
> +#define STATUS_DATATYPE_MISALIGNMENT	 0x80000002
> +#define STATUS_BREAKPOINT	 0x80000003
> +#define STATUS_SINGLE_STEP	 0x80000004
> +/* #define STATUS_BUFFER_OVERFLOW	 0x80000005 */
> +#define STATUS_NO_MORE_FILES	 0x80000006
> +#define STATUS_WAKE_SYSTEM_DEBUGGER	 0x80000007
> +#define STATUS_HANDLES_CLOSED	 0x8000000A
> +#define STATUS_NO_INHERITANCE	 0x8000000B
> +#define STATUS_GUID_SUBSTITUTION_MADE	 0x8000000C

Well, on the plus side, you did comment out STATUS_BUFFER_OVERFLOW
which was a definite conflict with the definitions in the SMB1 status
code list. However...I'm fairly certain that there are other conflicts
here, so that was just an example.

You really have two choices here:

1) make smb2status.h and nterr.h be mutually exclusive. Ensure that you
never #include both files. At first glance, this may be easy, but the
trick will be to ensure that no one does this in the future.

2) rename all of these error codes such that they do not conflict with
the SMB1 errors. This is more certain to ensure that you don't have
problems, but it's a bigger change.

I really don't care which one you choose, but we really do need to take
steps to ensure that we do not get conflicts here.

-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/22] CIFS: Make transport routines work with SMB2
       [not found]     ` <1340109611-7210-4-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
@ 2012-06-19 23:09       ` Jeff Layton
       [not found]         ` <20120619160946.6cb19f74-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
  0 siblings, 1 reply; 28+ messages in thread
From: Jeff Layton @ 2012-06-19 23:09 UTC (permalink / raw)
  To: Pavel Shilovsky; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Pavel Shilovsky

On Tue, 19 Jun 2012 16:39:52 +0400
Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:

> From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
> 
> Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
> ---
>  fs/cifs/Makefile        |    2 +-
>  fs/cifs/cifsglob.h      |    5 ++
>  fs/cifs/cifsproto.h     |    3 +-
>  fs/cifs/smb1ops.c       |    1 +
>  fs/cifs/smb2ops.c       |   18 ++++++
>  fs/cifs/smb2pdu.h       |   59 ++++++++++++++++++
>  fs/cifs/smb2proto.h     |    5 ++
>  fs/cifs/smb2transport.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++
>  fs/cifs/transport.c     |   13 ++--
>  9 files changed, 248 insertions(+), 9 deletions(-)
>  create mode 100644 fs/cifs/smb2transport.c
> 
> diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
> index 4a77271..a73d7f8 100644
> --- a/fs/cifs/Makefile
> +++ b/fs/cifs/Makefile
> @@ -16,4 +16,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
>  
>  cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
>  
> -cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o
> +cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 1266e2e..ae27ab8 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -22,6 +22,7 @@
>  #include <linux/in.h>
>  #include <linux/in6.h>
>  #include <linux/slab.h>
> +#include <linux/mempool.h>
>  #include <linux/workqueue.h>
>  #include "cifs_fs_sb.h"
>  #include "cifsacl.h"
> @@ -218,6 +219,7 @@ struct smb_version_values {
>  	size_t		header_size;
>  	size_t		max_header_size;
>  	size_t		read_rsp_size;
> +	__le16		lock_cmd;
>  };
>  
>  #define HEADER_SIZE(server) (server->vals->header_size)
> @@ -812,6 +814,7 @@ typedef void (mid_callback_t)(struct mid_q_entry *mid);
>  /* one of these for every pending CIFS request to the server */
>  struct mid_q_entry {
>  	struct list_head qhead;	/* mids waiting on reply from this server */
> +	struct TCP_Server_Info *server;	/* server corresponding to this mid */
>  	__u64 mid;		/* multiplex id */
>  	__u32 pid;		/* process id */
>  	__u32 sequence_number;  /* for CIFS signing */
> @@ -1153,6 +1156,8 @@ void cifs_oplock_break(struct work_struct *work);
>  extern const struct slow_work_ops cifs_oplock_break_ops;
>  extern struct workqueue_struct *cifsiod_wq;
>  
> +extern mempool_t *cifs_mid_poolp;
> +
>  /* Operations for different SMB versions */
>  #define SMB1_VERSION_STRING	"1.0"
>  extern struct smb_version_operations smb1_operations;
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 2f4f661..c45adfa 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -36,7 +36,7 @@ extern void cifs_buf_release(void *);
>  extern struct smb_hdr *cifs_small_buf_get(void);
>  extern void cifs_small_buf_release(void *);
>  extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
> -			unsigned int /* length */);
> +		    unsigned int /* length */);

Unneeded change?

>  extern unsigned int _GetXid(void);
>  extern void _FreeXid(unsigned int);
>  #define GetXid()						\
> @@ -68,6 +68,7 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
>  extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
>  					struct TCP_Server_Info *server);
>  extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
> +extern void cifs_wake_up_task(struct mid_q_entry *mid);
>  extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
>  			   unsigned int nvec, mid_receive_t *receive,
>  			   mid_callback_t *callback, void *cbdata,
> diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
> index 1a3f08c..cd7fbfd 100644
> --- a/fs/cifs/smb1ops.c
> +++ b/fs/cifs/smb1ops.c
> @@ -445,4 +445,5 @@ struct smb_version_values smb1_values = {
>  	.header_size = sizeof(struct smb_hdr),
>  	.max_header_size = MAX_CIFS_HDR_SIZE,
>  	.read_rsp_size = sizeof(READ_RSP),
> +	.lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
>  };
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index f065e89..80d9674 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -18,10 +18,28 @@
>   */
>  
>  #include "cifsglob.h"
> +#include "smb2pdu.h"
> +#include "smb2proto.h"
> +
> +static __u64
> +smb2_get_next_mid(struct TCP_Server_Info *server)
> +{
> +	__u64 mid;
> +	/* for SMB2 we need the current value */
> +	spin_lock(&GlobalMid_Lock);
> +	mid = server->CurrentMid;
> +	server->CurrentMid++;

	mid = server->CurrentMid++;

> +	spin_unlock(&GlobalMid_Lock);
> +	return mid;
> +}
>  
>  struct smb_version_operations smb21_operations = {
> +	.setup_request = smb2_setup_request,
> +	.check_receive = smb2_check_receive,
> +	.get_next_mid = smb2_get_next_mid,
>  };
>  
>  struct smb_version_values smb21_values = {
>  	.version_string = SMB21_VERSION_STRING,
> +	.lock_cmd = SMB2_LOCK,
>  };
> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
> index d35ac68..ed73201 100644
> --- a/fs/cifs/smb2pdu.h
> +++ b/fs/cifs/smb2pdu.h
> @@ -27,6 +27,65 @@
>  #include <net/sock.h>
>  
>  /*
> + * Note that, due to trying to use names similar to the protocol specifications,
> + * there are many mixed case field names in the structures below.  Although
> + * this does not match typical Linux kernel style, it is necessary to be
> + * be able to match against the protocol specfication.
> + *
> + * SMB2 commands
> + * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
> + * (ie no useful data other than the SMB error code itself) and are marked such.
> + * Knowing this helps avoid response buffer allocations and copy in some cases.
> + */
> +
> +/* List of commands in host endian */
> +#define SMB2NEGOTIATE		0x0000
> +#define SMB2SESSION_SETUP	0x0001
> +#define SMB2LOGOFF		0x0002 /* trivial request/resp */
> +#define SMB2TREE_CONNECT	0x0003
> +#define SMB2TREE_DISCONNECT	0x0004 /* trivial req/resp */
> +#define SMB2CREATE		0x0005
> +#define SMB2CLOSE		0x0006
> +#define SMB2FLUSH		0x0007 /* trivial resp */
> +#define SMB2READ		0x0008
> +#define SMB2WRITE		0x0009
> +#define SMB2LOCK		0x000A
> +#define SMB2IOCTL		0x000B
> +#define SMB2CANCEL		0x000C
> +#define SMB2ECHO		0x000D
> +#define SMB2QUERY_DIRECTORY	0x000E
> +#define SMB2CHANGE_NOTIFY	0x000F
> +#define SMB2QUERY_INFO		0x0010
> +#define SMB2SET_INFO		0x0011
> +#define SMB2OPLOCK_BREAK	0x0012
> +

I know that this is bikeshedding, but there's little difference between
these names and the ones below. That is going to result in bugs when we
get these mixed up (and we will).

Perhaps you should give the ones above more distinct names --
SMB2_NEGOTIATE_HE or something? Where _HE means host-endian?

> +/* The same list in little endian */
> +#define SMB2_NEGOTIATE		cpu_to_le16(SMB2NEGOTIATE)
> +#define SMB2_SESSION_SETUP	cpu_to_le16(SMB2SESSION_SETUP)
> +#define SMB2_LOGOFF		cpu_to_le16(SMB2LOGOFF)
> +#define SMB2_TREE_CONNECT	cpu_to_le16(SMB2TREE_CONNECT)
> +#define SMB2_TREE_DISCONNECT	cpu_to_le16(SMB2TREE_DISCONNECT)
> +#define SMB2_CREATE		cpu_to_le16(SMB2CREATE)
> +#define SMB2_CLOSE		cpu_to_le16(SMB2CLOSE)
> +#define SMB2_FLUSH		cpu_to_le16(SMB2FLUSH)
> +#define SMB2_READ		cpu_to_le16(SMB2READ)
> +#define SMB2_WRITE		cpu_to_le16(SMB2WRITE)
> +#define SMB2_LOCK		cpu_to_le16(SMB2LOCK)
> +#define SMB2_IOCTL		cpu_to_le16(SMB2IOCTL)
> +#define SMB2_CANCEL		cpu_to_le16(SMB2CANCEL)
> +#define SMB2_ECHO		cpu_to_le16(SMB2ECHO)
> +#define SMB2_QUERY_DIRECTORY	cpu_to_le16(SMB2QUERY_DIRECTORY)
> +#define SMB2_CHANGE_NOTIFY	cpu_to_le16(SMB2CHANGE_NOTIFY)
> +#define SMB2_QUERY_INFO		cpu_to_le16(SMB2QUERY_INFO)
> +#define SMB2_SET_INFO		cpu_to_le16(SMB2SET_INFO)
> +#define SMB2_OPLOCK_BREAK	cpu_to_le16(SMB2OPLOCK_BREAK)
> +
> +#define NUMBER_OF_SMB2_COMMANDS	0x0013
> +
> +/* BB FIXME - analyze following length BB */
> +#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
> +

Would it be better to define this in terms of sizeof(SMB2_LARGEST_HEADER_STRUCT) ?

> +/*
>   * SMB2 Header Definition
>   *
>   * "MBZ" :  Must be Zero
> diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
> index 08249ee..0e59afb 100644
> --- a/fs/cifs/smb2proto.h
> +++ b/fs/cifs/smb2proto.h
> @@ -34,4 +34,9 @@ struct statfs;
>   */
>  extern int map_smb2_to_linux_error(char *buf, bool log_err);
>  
> +extern int smb2_check_receive(struct mid_q_entry *mid,
> +			      struct TCP_Server_Info *server, bool log_error);
> +extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
> +			      unsigned int nvec, struct mid_q_entry **ret_mid);
> +
>  #endif			/* _SMB2PROTO_H */
> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
> new file mode 100644
> index 0000000..74830f2
> --- /dev/null
> +++ b/fs/cifs/smb2transport.c
> @@ -0,0 +1,151 @@
> +/*
> + *   fs/cifs/smb2transport.c
> + *
> + *   Copyright (C) International Business Machines  Corp., 2002, 2011
> + *                 Etersoft, 2012
> + *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
> + *              Jeremy Allison (jra-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2006
> + *              Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2012
> + *
> + *   This library is free software; you can redistribute it and/or modify
> + *   it under the terms of the GNU Lesser General Public License as published
> + *   by the Free Software Foundation; either version 2.1 of the License, or
> + *   (at your option) any later version.
> + *
> + *   This library is distributed in the hope that it will be useful,
> + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> + *   the GNU Lesser General Public License for more details.
> + *
> + *   You should have received a copy of the GNU Lesser General Public License
> + *   along with this library; if not, write to the Free Software
> + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#include <linux/fs.h>
> +#include <linux/list.h>
> +#include <linux/wait.h>
> +#include <linux/net.h>
> +#include <linux/delay.h>
> +#include <linux/uaccess.h>
> +#include <asm/processor.h>
> +#include <linux/mempool.h>
> +#include "smb2pdu.h"
> +#include "cifsglob.h"
> +#include "cifsproto.h"
> +#include "smb2proto.h"
> +#include "cifs_debug.h"
> +#include "smb2status.h"
> +
> +/*
> + * Set message id for the request. Should be called after wait_for_free_request
> + * and when srv_mutex is held. iov array must have at least 1 element.
> + */
> +static inline void
> +smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct kvec *iov)

Why pass in a kvec here? Maybe a smb2_hdr pointer instead?

> +{
> +	((struct smb2_hdr *)iov[0].iov_base)->MessageId = get_next_mid(server);
> +}
> +
> +static struct mid_q_entry *
> +smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
> +		     struct TCP_Server_Info *server)
> +{
> +	struct mid_q_entry *temp;
> +
> +	if (server == NULL) {
> +		cERROR(1, "Null TCP session in smb2_mid_entry_alloc");
> +		return NULL;
> +	}
> +
> +	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
> +	if (temp == NULL)
> +		return temp;
> +	else {
> +		memset(temp, 0, sizeof(struct mid_q_entry));
> +		temp->mid = smb_buffer->MessageId;	/* always LE */
> +		temp->pid = current->pid;
> +		temp->command = smb_buffer->Command;	/* Always LE */
> +		temp->when_alloc = jiffies;
> +		temp->server = server;
> +
> +		/*
> +		 * The default is for the mid to be synchronous, so the
> +		 * default callback just wakes up the current task.
> +		 */
> +		temp->callback = cifs_wake_up_task;
> +		temp->callback_data = current;
> +	}
> +
> +	atomic_inc(&midCount);
> +	temp->mid_state = MID_REQUEST_ALLOCATED;
> +	return temp;
> +}
> +
> +static int
> +smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
> +		   struct mid_q_entry **mid)
> +{
> +	if (ses->server->tcpStatus == CifsExiting)
> +		return -ENOENT;
> +
> +	if (ses->server->tcpStatus == CifsNeedReconnect) {
> +		cFYI(1, "tcp session dead - return to caller to retry");
> +		return -EAGAIN;
> +	}
> +
> +	if (ses->status != CifsGood) {
> +		/* check if SMB2 session is bad because we are setting it up */
> +		if ((buf->Command != SMB2_SESSION_SETUP) &&
> +		    (buf->Command != SMB2_NEGOTIATE))
> +			return -EAGAIN;
> +		/* else ok - we are setting up session */
> +	}
> +	*mid = smb2_mid_entry_alloc(buf, ses->server);
> +	if (*mid == NULL)
> +		return -ENOMEM;
> +	spin_lock(&GlobalMid_Lock);
> +	list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
> +	spin_unlock(&GlobalMid_Lock);
> +	return 0;
> +}
> +
> +int
> +smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
> +		   bool log_error)
> +{
> +	unsigned int len = get_rfc1002_length(mid->resp_buf);
> +
> +	dump_smb(mid->resp_buf, min_t(u32, 80, len));
> +	/* convert the length into a more usable form */
> +	/* BB - uncomment with SMB2 signing implementation */
> +	/* if ((len > 24) &&
> +	    (server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) {
> +		if (smb2_verify_signature(mid->resp_buf, server))
> +			cERROR(1, "Unexpected SMB signature");
> +	} */
> +
> +	return map_smb2_to_linux_error(mid->resp_buf, log_error);
> +}
> +
> +int
> +smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
> +		   unsigned int nvec, struct mid_q_entry **ret_mid)
> +{
> +	int rc;
> +	struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
> +	struct mid_q_entry *mid;
> +
> +	smb2_seq_num_into_buf(ses->server, iov);
> +
> +	rc = smb2_get_mid_entry(ses, hdr, &mid);
> +	if (rc)
> +		return rc;
> +	/* rc = smb2_sign_smb2(iov, nvec, ses->server);
> +	if (rc)
> +		delete_mid(mid); */
> +	*ret_mid = mid;
> +	return rc;
> +}
> +
> +/* BB add missing functions here */
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 54cd8dd..ea86753 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -35,10 +35,8 @@
>  #include "cifsproto.h"
>  #include "cifs_debug.h"
>  
> -extern mempool_t *cifs_mid_poolp;
> -
> -static void
> -wake_up_task(struct mid_q_entry *mid)
> +void
> +cifs_wake_up_task(struct mid_q_entry *mid)
>  {
>  	wake_up_process(mid->callback_data);
>  }
> @@ -65,12 +63,13 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
>  	/*	do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
>  		/* when mid allocated can be before when sent */
>  		temp->when_alloc = jiffies;
> +		temp->server = server;
>  
>  		/*
>  		 * The default is for the mid to be synchronous, so the
>  		 * default callback just wakes up the current task.
>  		 */
> -		temp->callback = wake_up_task;
> +		temp->callback = cifs_wake_up_task;
>  		temp->callback_data = current;
>  	}
>  
> @@ -83,6 +82,7 @@ void
>  DeleteMidQEntry(struct mid_q_entry *midEntry)
>  {
>  #ifdef CONFIG_CIFS_STATS2
> +	__le16 command = midEntry->server->vals->lock_cmd;
>  	unsigned long now;
>  #endif
>  	midEntry->mid_state = MID_FREE;
> @@ -96,8 +96,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
>  	/* commands taking longer than one second are indications that
>  	   something is wrong, unless it is quite a slow link or server */
>  	if ((now - midEntry->when_alloc) > HZ) {
> -		if ((cifsFYI & CIFS_TIMER) &&
> -		    (midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) {
> +		if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
>  			printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
>  			       midEntry->command, midEntry->mid);
>  			printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",


-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/22] CIFS: Add SMB2 status codes
       [not found]         ` <20120619152207.6d48ec92-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
@ 2012-06-20  7:49           ` Pavel Shilovsky
       [not found]             ` <CAKywueRzeAV2P-nO=K3kpVaLoh=i462kaLaLGgJvEs4Mrteh1w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-20  7:49 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/6/20 Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
> On Tue, 19 Jun 2012 16:39:50 +0400
> Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
>
>> +#define STATUS_GUARD_PAGE_VIOLATION   0x80000001
>> +#define STATUS_DATATYPE_MISALIGNMENT  0x80000002
>> +#define STATUS_BREAKPOINT     0x80000003
>> +#define STATUS_SINGLE_STEP    0x80000004
>> +/* #define STATUS_BUFFER_OVERFLOW     0x80000005 */
>> +#define STATUS_NO_MORE_FILES  0x80000006
>> +#define STATUS_WAKE_SYSTEM_DEBUGGER   0x80000007
>> +#define STATUS_HANDLES_CLOSED         0x8000000A
>> +#define STATUS_NO_INHERITANCE         0x8000000B
>> +#define STATUS_GUID_SUBSTITUTION_MADE         0x8000000C
>
> Well, on the plus side, you did comment out STATUS_BUFFER_OVERFLOW
> which was a definite conflict with the definitions in the SMB1 status
> code list. However...I'm fairly certain that there are other conflicts
> here, so that was just an example.
>
> You really have two choices here:
>
> 1) make smb2status.h and nterr.h be mutually exclusive. Ensure that you
> never #include both files. At first glance, this may be easy, but the
> trick will be to ensure that no one does this in the future.
>
> 2) rename all of these error codes such that they do not conflict with
> the SMB1 errors. This is more certain to ensure that you don't have
> problems, but it's a bigger change.
>
> I really don't care which one you choose, but we really do need to take
> steps to ensure that we do not get conflicts here.
>
> --
> Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

nterr.h has only 5 macros started with STATUS_:

#define STATUS_MORE_ENTRIES               0x0105
#define STATUS_1804>----                  0x070c
#define STATUS_NOTIFY_ENUM_DIR            0x010c
#define STATUS_SOME_UNMAPPED       0x0107
#define STATUS_BUFFER_OVERFLOW     0x80000005

I've already checked all them and commented dublicates in smb2status.h
(STATUS_MORE_ENTRIES, STATUS_NOTIFY_ENUM_DIR, STATUS_BUFFER_OVERFLOW)
- no conflicts now.

But I don't care to rename all error codes to something like
SMB2_STATUS_ to make sure we will not miss something in future.

-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/22] CIFS: Make transport routines work with SMB2
       [not found]         ` <20120619160946.6cb19f74-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
@ 2012-06-20  9:46           ` Pavel Shilovsky
  0 siblings, 0 replies; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-20  9:46 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/6/20 Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
> On Tue, 19 Jun 2012 16:39:52 +0400
> Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
>
>> From: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
>>
>> Signed-off-by: Pavel Shilovsky <piastry-7qunaywFIewox3rIn2DAYQ@public.gmane.org>
>> ---
>>  fs/cifs/Makefile        |    2 +-
>>  fs/cifs/cifsglob.h      |    5 ++
>>  fs/cifs/cifsproto.h     |    3 +-
>>  fs/cifs/smb1ops.c       |    1 +
>>  fs/cifs/smb2ops.c       |   18 ++++++
>>  fs/cifs/smb2pdu.h       |   59 ++++++++++++++++++
>>  fs/cifs/smb2proto.h     |    5 ++
>>  fs/cifs/smb2transport.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++
>>  fs/cifs/transport.c     |   13 ++--
>>  9 files changed, 248 insertions(+), 9 deletions(-)
>>  create mode 100644 fs/cifs/smb2transport.c
>>
>> diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
>> index 4a77271..a73d7f8 100644
>> --- a/fs/cifs/Makefile
>> +++ b/fs/cifs/Makefile
>> @@ -16,4 +16,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
>>
>>  cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
>>
>> -cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o
>> +cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o
>> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
>> index 1266e2e..ae27ab8 100644
>> --- a/fs/cifs/cifsglob.h
>> +++ b/fs/cifs/cifsglob.h
>> @@ -22,6 +22,7 @@
>>  #include <linux/in.h>
>>  #include <linux/in6.h>
>>  #include <linux/slab.h>
>> +#include <linux/mempool.h>
>>  #include <linux/workqueue.h>
>>  #include "cifs_fs_sb.h"
>>  #include "cifsacl.h"
>> @@ -218,6 +219,7 @@ struct smb_version_values {
>>       size_t          header_size;
>>       size_t          max_header_size;
>>       size_t          read_rsp_size;
>> +     __le16          lock_cmd;
>>  };
>>
>>  #define HEADER_SIZE(server) (server->vals->header_size)
>> @@ -812,6 +814,7 @@ typedef void (mid_callback_t)(struct mid_q_entry *mid);
>>  /* one of these for every pending CIFS request to the server */
>>  struct mid_q_entry {
>>       struct list_head qhead; /* mids waiting on reply from this server */
>> +     struct TCP_Server_Info *server; /* server corresponding to this mid */
>>       __u64 mid;              /* multiplex id */
>>       __u32 pid;              /* process id */
>>       __u32 sequence_number;  /* for CIFS signing */
>> @@ -1153,6 +1156,8 @@ void cifs_oplock_break(struct work_struct *work);
>>  extern const struct slow_work_ops cifs_oplock_break_ops;
>>  extern struct workqueue_struct *cifsiod_wq;
>>
>> +extern mempool_t *cifs_mid_poolp;
>> +
>>  /* Operations for different SMB versions */
>>  #define SMB1_VERSION_STRING  "1.0"
>>  extern struct smb_version_operations smb1_operations;
>> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>> index 2f4f661..c45adfa 100644
>> --- a/fs/cifs/cifsproto.h
>> +++ b/fs/cifs/cifsproto.h
>> @@ -36,7 +36,7 @@ extern void cifs_buf_release(void *);
>>  extern struct smb_hdr *cifs_small_buf_get(void);
>>  extern void cifs_small_buf_release(void *);
>>  extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
>> -                     unsigned int /* length */);
>> +                 unsigned int /* length */);
>
> Unneeded change?

Yes :)

>
>>  extern unsigned int _GetXid(void);
>>  extern void _FreeXid(unsigned int);
>>  #define GetXid()                                             \
>> @@ -68,6 +68,7 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
>>  extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
>>                                       struct TCP_Server_Info *server);
>>  extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
>> +extern void cifs_wake_up_task(struct mid_q_entry *mid);
>>  extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
>>                          unsigned int nvec, mid_receive_t *receive,
>>                          mid_callback_t *callback, void *cbdata,
>> diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
>> index 1a3f08c..cd7fbfd 100644
>> --- a/fs/cifs/smb1ops.c
>> +++ b/fs/cifs/smb1ops.c
>> @@ -445,4 +445,5 @@ struct smb_version_values smb1_values = {
>>       .header_size = sizeof(struct smb_hdr),
>>       .max_header_size = MAX_CIFS_HDR_SIZE,
>>       .read_rsp_size = sizeof(READ_RSP),
>> +     .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
>>  };
>> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
>> index f065e89..80d9674 100644
>> --- a/fs/cifs/smb2ops.c
>> +++ b/fs/cifs/smb2ops.c
>> @@ -18,10 +18,28 @@
>>   */
>>
>>  #include "cifsglob.h"
>> +#include "smb2pdu.h"
>> +#include "smb2proto.h"
>> +
>> +static __u64
>> +smb2_get_next_mid(struct TCP_Server_Info *server)
>> +{
>> +     __u64 mid;
>> +     /* for SMB2 we need the current value */
>> +     spin_lock(&GlobalMid_Lock);
>> +     mid = server->CurrentMid;
>> +     server->CurrentMid++;
>
>        mid = server->CurrentMid++;
>
>> +     spin_unlock(&GlobalMid_Lock);
>> +     return mid;
>> +}
>>
>>  struct smb_version_operations smb21_operations = {
>> +     .setup_request = smb2_setup_request,
>> +     .check_receive = smb2_check_receive,
>> +     .get_next_mid = smb2_get_next_mid,
>>  };
>>
>>  struct smb_version_values smb21_values = {
>>       .version_string = SMB21_VERSION_STRING,
>> +     .lock_cmd = SMB2_LOCK,
>>  };
>> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
>> index d35ac68..ed73201 100644
>> --- a/fs/cifs/smb2pdu.h
>> +++ b/fs/cifs/smb2pdu.h
>> @@ -27,6 +27,65 @@
>>  #include <net/sock.h>
>>
>>  /*
>> + * Note that, due to trying to use names similar to the protocol specifications,
>> + * there are many mixed case field names in the structures below.  Although
>> + * this does not match typical Linux kernel style, it is necessary to be
>> + * be able to match against the protocol specfication.
>> + *
>> + * SMB2 commands
>> + * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
>> + * (ie no useful data other than the SMB error code itself) and are marked such.
>> + * Knowing this helps avoid response buffer allocations and copy in some cases.
>> + */
>> +
>> +/* List of commands in host endian */
>> +#define SMB2NEGOTIATE                0x0000
>> +#define SMB2SESSION_SETUP    0x0001
>> +#define SMB2LOGOFF           0x0002 /* trivial request/resp */
>> +#define SMB2TREE_CONNECT     0x0003
>> +#define SMB2TREE_DISCONNECT  0x0004 /* trivial req/resp */
>> +#define SMB2CREATE           0x0005
>> +#define SMB2CLOSE            0x0006
>> +#define SMB2FLUSH            0x0007 /* trivial resp */
>> +#define SMB2READ             0x0008
>> +#define SMB2WRITE            0x0009
>> +#define SMB2LOCK             0x000A
>> +#define SMB2IOCTL            0x000B
>> +#define SMB2CANCEL           0x000C
>> +#define SMB2ECHO             0x000D
>> +#define SMB2QUERY_DIRECTORY  0x000E
>> +#define SMB2CHANGE_NOTIFY    0x000F
>> +#define SMB2QUERY_INFO               0x0010
>> +#define SMB2SET_INFO         0x0011
>> +#define SMB2OPLOCK_BREAK     0x0012
>> +
>
> I know that this is bikeshedding, but there's little difference between
> these names and the ones below. That is going to result in bugs when we
> get these mixed up (and we will).
>
> Perhaps you should give the ones above more distinct names --
> SMB2_NEGOTIATE_HE or something? Where _HE means host-endian?
>
>> +/* The same list in little endian */
>> +#define SMB2_NEGOTIATE               cpu_to_le16(SMB2NEGOTIATE)
>> +#define SMB2_SESSION_SETUP   cpu_to_le16(SMB2SESSION_SETUP)
>> +#define SMB2_LOGOFF          cpu_to_le16(SMB2LOGOFF)
>> +#define SMB2_TREE_CONNECT    cpu_to_le16(SMB2TREE_CONNECT)
>> +#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2TREE_DISCONNECT)
>> +#define SMB2_CREATE          cpu_to_le16(SMB2CREATE)
>> +#define SMB2_CLOSE           cpu_to_le16(SMB2CLOSE)
>> +#define SMB2_FLUSH           cpu_to_le16(SMB2FLUSH)
>> +#define SMB2_READ            cpu_to_le16(SMB2READ)
>> +#define SMB2_WRITE           cpu_to_le16(SMB2WRITE)
>> +#define SMB2_LOCK            cpu_to_le16(SMB2LOCK)
>> +#define SMB2_IOCTL           cpu_to_le16(SMB2IOCTL)
>> +#define SMB2_CANCEL          cpu_to_le16(SMB2CANCEL)
>> +#define SMB2_ECHO            cpu_to_le16(SMB2ECHO)
>> +#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2QUERY_DIRECTORY)
>> +#define SMB2_CHANGE_NOTIFY   cpu_to_le16(SMB2CHANGE_NOTIFY)
>> +#define SMB2_QUERY_INFO              cpu_to_le16(SMB2QUERY_INFO)
>> +#define SMB2_SET_INFO                cpu_to_le16(SMB2SET_INFO)
>> +#define SMB2_OPLOCK_BREAK    cpu_to_le16(SMB2OPLOCK_BREAK)
>> +
>> +#define NUMBER_OF_SMB2_COMMANDS      0x0013
>> +
>> +/* BB FIXME - analyze following length BB */
>> +#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
>> +
>
> Would it be better to define this in terms of sizeof(SMB2_LARGEST_HEADER_STRUCT) ?

Now we only define smb2_hdr structure - we can fix this value further
than SMB2_LARGEST_HEADER_STRUCT appears.

>
>> +/*
>>   * SMB2 Header Definition
>>   *
>>   * "MBZ" :  Must be Zero
>> diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
>> index 08249ee..0e59afb 100644
>> --- a/fs/cifs/smb2proto.h
>> +++ b/fs/cifs/smb2proto.h
>> @@ -34,4 +34,9 @@ struct statfs;
>>   */
>>  extern int map_smb2_to_linux_error(char *buf, bool log_err);
>>
>> +extern int smb2_check_receive(struct mid_q_entry *mid,
>> +                           struct TCP_Server_Info *server, bool log_error);
>> +extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
>> +                           unsigned int nvec, struct mid_q_entry **ret_mid);
>> +
>>  #endif                       /* _SMB2PROTO_H */
>> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
>> new file mode 100644
>> index 0000000..74830f2
>> --- /dev/null
>> +++ b/fs/cifs/smb2transport.c
>> @@ -0,0 +1,151 @@
>> +/*
>> + *   fs/cifs/smb2transport.c
>> + *
>> + *   Copyright (C) International Business Machines  Corp., 2002, 2011
>> + *                 Etersoft, 2012
>> + *   Author(s): Steve French (sfrench-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)
>> + *              Jeremy Allison (jra-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2006
>> + *              Pavel Shilovsky (pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org) 2012
>> + *
>> + *   This library is free software; you can redistribute it and/or modify
>> + *   it under the terms of the GNU Lesser General Public License as published
>> + *   by the Free Software Foundation; either version 2.1 of the License, or
>> + *   (at your option) any later version.
>> + *
>> + *   This library is distributed in the hope that it will be useful,
>> + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>> + *   the GNU Lesser General Public License for more details.
>> + *
>> + *   You should have received a copy of the GNU Lesser General Public License
>> + *   along with this library; if not, write to the Free Software
>> + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>> + */
>> +
>> +#include <linux/fs.h>
>> +#include <linux/list.h>
>> +#include <linux/wait.h>
>> +#include <linux/net.h>
>> +#include <linux/delay.h>
>> +#include <linux/uaccess.h>
>> +#include <asm/processor.h>
>> +#include <linux/mempool.h>
>> +#include "smb2pdu.h"
>> +#include "cifsglob.h"
>> +#include "cifsproto.h"
>> +#include "smb2proto.h"
>> +#include "cifs_debug.h"
>> +#include "smb2status.h"
>> +
>> +/*
>> + * Set message id for the request. Should be called after wait_for_free_request
>> + * and when srv_mutex is held. iov array must have at least 1 element.
>> + */
>> +static inline void
>> +smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct kvec *iov)
>
> Why pass in a kvec here? Maybe a smb2_hdr pointer instead?

Yes, it makes sense.

>
>> +{
>> +     ((struct smb2_hdr *)iov[0].iov_base)->MessageId = get_next_mid(server);
>> +}
>> +
>> +static struct mid_q_entry *
>> +smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
>> +                  struct TCP_Server_Info *server)
>> +{
>> +     struct mid_q_entry *temp;
>> +
>> +     if (server == NULL) {
>> +             cERROR(1, "Null TCP session in smb2_mid_entry_alloc");
>> +             return NULL;
>> +     }
>> +
>> +     temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
>> +     if (temp == NULL)
>> +             return temp;
>> +     else {
>> +             memset(temp, 0, sizeof(struct mid_q_entry));
>> +             temp->mid = smb_buffer->MessageId;      /* always LE */
>> +             temp->pid = current->pid;
>> +             temp->command = smb_buffer->Command;    /* Always LE */
>> +             temp->when_alloc = jiffies;
>> +             temp->server = server;
>> +
>> +             /*
>> +              * The default is for the mid to be synchronous, so the
>> +              * default callback just wakes up the current task.
>> +              */
>> +             temp->callback = cifs_wake_up_task;
>> +             temp->callback_data = current;
>> +     }
>> +
>> +     atomic_inc(&midCount);
>> +     temp->mid_state = MID_REQUEST_ALLOCATED;
>> +     return temp;
>> +}
>> +
>> +static int
>> +smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
>> +                struct mid_q_entry **mid)
>> +{
>> +     if (ses->server->tcpStatus == CifsExiting)
>> +             return -ENOENT;
>> +
>> +     if (ses->server->tcpStatus == CifsNeedReconnect) {
>> +             cFYI(1, "tcp session dead - return to caller to retry");
>> +             return -EAGAIN;
>> +     }
>> +
>> +     if (ses->status != CifsGood) {
>> +             /* check if SMB2 session is bad because we are setting it up */
>> +             if ((buf->Command != SMB2_SESSION_SETUP) &&
>> +                 (buf->Command != SMB2_NEGOTIATE))
>> +                     return -EAGAIN;
>> +             /* else ok - we are setting up session */
>> +     }
>> +     *mid = smb2_mid_entry_alloc(buf, ses->server);
>> +     if (*mid == NULL)
>> +             return -ENOMEM;
>> +     spin_lock(&GlobalMid_Lock);
>> +     list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
>> +     spin_unlock(&GlobalMid_Lock);
>> +     return 0;
>> +}
>> +
>> +int
>> +smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
>> +                bool log_error)
>> +{
>> +     unsigned int len = get_rfc1002_length(mid->resp_buf);
>> +
>> +     dump_smb(mid->resp_buf, min_t(u32, 80, len));
>> +     /* convert the length into a more usable form */
>> +     /* BB - uncomment with SMB2 signing implementation */
>> +     /* if ((len > 24) &&
>> +         (server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) {
>> +             if (smb2_verify_signature(mid->resp_buf, server))
>> +                     cERROR(1, "Unexpected SMB signature");
>> +     } */
>> +
>> +     return map_smb2_to_linux_error(mid->resp_buf, log_error);
>> +}
>> +
>> +int
>> +smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
>> +                unsigned int nvec, struct mid_q_entry **ret_mid)
>> +{
>> +     int rc;
>> +     struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
>> +     struct mid_q_entry *mid;
>> +
>> +     smb2_seq_num_into_buf(ses->server, iov);
>> +
>> +     rc = smb2_get_mid_entry(ses, hdr, &mid);
>> +     if (rc)
>> +             return rc;
>> +     /* rc = smb2_sign_smb2(iov, nvec, ses->server);
>> +     if (rc)
>> +             delete_mid(mid); */
>> +     *ret_mid = mid;
>> +     return rc;
>> +}
>> +
>> +/* BB add missing functions here */
>> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
>> index 54cd8dd..ea86753 100644
>> --- a/fs/cifs/transport.c
>> +++ b/fs/cifs/transport.c
>> @@ -35,10 +35,8 @@
>>  #include "cifsproto.h"
>>  #include "cifs_debug.h"
>>
>> -extern mempool_t *cifs_mid_poolp;
>> -
>> -static void
>> -wake_up_task(struct mid_q_entry *mid)
>> +void
>> +cifs_wake_up_task(struct mid_q_entry *mid)
>>  {
>>       wake_up_process(mid->callback_data);
>>  }
>> @@ -65,12 +63,13 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
>>       /*      do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
>>               /* when mid allocated can be before when sent */
>>               temp->when_alloc = jiffies;
>> +             temp->server = server;
>>
>>               /*
>>                * The default is for the mid to be synchronous, so the
>>                * default callback just wakes up the current task.
>>                */
>> -             temp->callback = wake_up_task;
>> +             temp->callback = cifs_wake_up_task;
>>               temp->callback_data = current;
>>       }
>>
>> @@ -83,6 +82,7 @@ void
>>  DeleteMidQEntry(struct mid_q_entry *midEntry)
>>  {
>>  #ifdef CONFIG_CIFS_STATS2
>> +     __le16 command = midEntry->server->vals->lock_cmd;
>>       unsigned long now;
>>  #endif
>>       midEntry->mid_state = MID_FREE;
>> @@ -96,8 +96,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
>>       /* commands taking longer than one second are indications that
>>          something is wrong, unless it is quite a slow link or server */
>>       if ((now - midEntry->when_alloc) > HZ) {
>> -             if ((cifsFYI & CIFS_TIMER) &&
>> -                 (midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) {
>> +             if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
>>                       printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
>>                              midEntry->command, midEntry->mid);
>>                       printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
>
>
> --
> Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>



-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/22] CIFS: Add SMB2 status codes
       [not found]             ` <CAKywueRzeAV2P-nO=K3kpVaLoh=i462kaLaLGgJvEs4Mrteh1w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-06-20 14:33               ` Pavel Shilovsky
       [not found]                 ` <CAKywueQVavHPXaK6KvPUR6LSEo-h4wqOZt4xDGs1dpbkFBckVQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 28+ messages in thread
From: Pavel Shilovsky @ 2012-06-20 14:33 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

2012/6/20 Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
> 2012/6/20 Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
>> On Tue, 19 Jun 2012 16:39:50 +0400
>> Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
>>
>>> +#define STATUS_GUARD_PAGE_VIOLATION   0x80000001
>>> +#define STATUS_DATATYPE_MISALIGNMENT  0x80000002
>>> +#define STATUS_BREAKPOINT     0x80000003
>>> +#define STATUS_SINGLE_STEP    0x80000004
>>> +/* #define STATUS_BUFFER_OVERFLOW     0x80000005 */
>>> +#define STATUS_NO_MORE_FILES  0x80000006
>>> +#define STATUS_WAKE_SYSTEM_DEBUGGER   0x80000007
>>> +#define STATUS_HANDLES_CLOSED         0x8000000A
>>> +#define STATUS_NO_INHERITANCE         0x8000000B
>>> +#define STATUS_GUID_SUBSTITUTION_MADE         0x8000000C
>>
>> Well, on the plus side, you did comment out STATUS_BUFFER_OVERFLOW
>> which was a definite conflict with the definitions in the SMB1 status
>> code list. However...I'm fairly certain that there are other conflicts
>> here, so that was just an example.
>>
>> You really have two choices here:
>>
>> 1) make smb2status.h and nterr.h be mutually exclusive. Ensure that you
>> never #include both files. At first glance, this may be easy, but the
>> trick will be to ensure that no one does this in the future.
>>
>> 2) rename all of these error codes such that they do not conflict with
>> the SMB1 errors. This is more certain to ensure that you don't have
>> problems, but it's a bigger change.
>>
>> I really don't care which one you choose, but we really do need to take
>> steps to ensure that we do not get conflicts here.
>>
>> --
>> Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
>
> nterr.h has only 5 macros started with STATUS_:
>
> #define STATUS_MORE_ENTRIES               0x0105
> #define STATUS_1804>----                  0x070c
> #define STATUS_NOTIFY_ENUM_DIR            0x010c
> #define STATUS_SOME_UNMAPPED       0x0107
> #define STATUS_BUFFER_OVERFLOW     0x80000005
>
> I've already checked all them and commented dublicates in smb2status.h
> (STATUS_MORE_ENTRIES, STATUS_NOTIFY_ENUM_DIR, STATUS_BUFFER_OVERFLOW)
> - no conflicts now.
>
> But I don't care to rename all error codes to something like
> SMB2_STATUS_ to make sure we will not miss something in future.
>
> --
> Best regards,
> Pavel Shilovsky.

After a discussion with Jeff we came to the following rules:
1) prefix 7 error codes from nterr.h with NT_ that doesn't thave NT_
and consider them as CIFS codes.
2) consider codes from smb2status.h patch as new style codes (suitable
for SMB2, SMB2.1 and SMB3).

-- 
Best regards,
Pavel Shilovsky.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/22] CIFS: Add SMB2 status codes
       [not found]                 ` <CAKywueQVavHPXaK6KvPUR6LSEo-h4wqOZt4xDGs1dpbkFBckVQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-06-20 23:49                   ` Steve French
  0 siblings, 0 replies; 28+ messages in thread
From: Steve French @ 2012-06-20 23:49 UTC (permalink / raw)
  To: Pavel Shilovsky; +Cc: Jeff Layton, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Wed, Jun 20, 2012 at 7:33 AM, Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> 2012/6/20 Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
>> 2012/6/20 Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
>>> On Tue, 19 Jun 2012 16:39:50 +0400
>>> Pavel Shilovsky <pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
>>>
>>>> +#define STATUS_GUARD_PAGE_VIOLATION   0x80000001
>>>> +#define STATUS_DATATYPE_MISALIGNMENT  0x80000002
>>>> +#define STATUS_BREAKPOINT     0x80000003
>>>> +#define STATUS_SINGLE_STEP    0x80000004
>>>> +/* #define STATUS_BUFFER_OVERFLOW     0x80000005 */
>>>> +#define STATUS_NO_MORE_FILES  0x80000006
>>>> +#define STATUS_WAKE_SYSTEM_DEBUGGER   0x80000007
>>>> +#define STATUS_HANDLES_CLOSED         0x8000000A
>>>> +#define STATUS_NO_INHERITANCE         0x8000000B
>>>> +#define STATUS_GUID_SUBSTITUTION_MADE         0x8000000C
>>>
>>> Well, on the plus side, you did comment out STATUS_BUFFER_OVERFLOW
>>> which was a definite conflict with the definitions in the SMB1 status
>>> code list. However...I'm fairly certain that there are other conflicts
>>> here, so that was just an example.
>>>
>>> You really have two choices here:
>>>
>>> 1) make smb2status.h and nterr.h be mutually exclusive. Ensure that you
>>> never #include both files. At first glance, this may be easy, but the
>>> trick will be to ensure that no one does this in the future.
>>>
>>> 2) rename all of these error codes such that they do not conflict with
>>> the SMB1 errors. This is more certain to ensure that you don't have
>>> problems, but it's a bigger change.
>>>
>>> I really don't care which one you choose, but we really do need to take
>>> steps to ensure that we do not get conflicts here.
>>>
>>> --
>>> Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
>>
>> nterr.h has only 5 macros started with STATUS_:
>>
>> #define STATUS_MORE_ENTRIES               0x0105
>> #define STATUS_1804>----                  0x070c
>> #define STATUS_NOTIFY_ENUM_DIR            0x010c
>> #define STATUS_SOME_UNMAPPED       0x0107
>> #define STATUS_BUFFER_OVERFLOW     0x80000005
>>
>> I've already checked all them and commented dublicates in smb2status.h
>> (STATUS_MORE_ENTRIES, STATUS_NOTIFY_ENUM_DIR, STATUS_BUFFER_OVERFLOW)
>> - no conflicts now.
>>
>> But I don't care to rename all error codes to something like
>> SMB2_STATUS_ to make sure we will not miss something in future.
>>
>> --
>> Best regards,
>> Pavel Shilovsky.
>
> After a discussion with Jeff we came to the following rules:
> 1) prefix 7 error codes from nterr.h with NT_ that doesn't thave NT_
> and consider them as CIFS codes.
> 2) consider codes from smb2status.h patch as new style codes (suitable
> for SMB2, SMB2.1 and SMB3).

Yes - but also have to doublecheck that we didn't miss some new ones.



-- 
Thanks,

Steve

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2012-06-20 23:49 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-19 12:39 [PATCH 00/22] Get SMB2 mount work Pavel Shilovsky
     [not found] ` <1340109611-7210-1-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2012-06-19 12:39   ` [PATCH 01/22] CIFS: Add SMB2 status codes Pavel Shilovsky
     [not found]     ` <1340109611-7210-2-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2012-06-19 22:22       ` Jeff Layton
     [not found]         ` <20120619152207.6d48ec92-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2012-06-20  7:49           ` Pavel Shilovsky
     [not found]             ` <CAKywueRzeAV2P-nO=K3kpVaLoh=i462kaLaLGgJvEs4Mrteh1w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-06-20 14:33               ` Pavel Shilovsky
     [not found]                 ` <CAKywueQVavHPXaK6KvPUR6LSEo-h4wqOZt4xDGs1dpbkFBckVQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-06-20 23:49                   ` Steve French
2012-06-19 12:39   ` [PATCH 03/22] CIFS: Make transport routines work with SMB2 Pavel Shilovsky
     [not found]     ` <1340109611-7210-4-git-send-email-pshilovsky-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
2012-06-19 23:09       ` Jeff Layton
     [not found]         ` <20120619160946.6cb19f74-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2012-06-20  9:46           ` Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 04/22] CIFS: Add SMB2 credits support Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 05/22] CIFS: Make demultiplex_thread work with SMB2 code Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 06/22] CIFS: Respect SMB2 header/max header size Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 07/22] CIFS: Add capability to send SMB2 negotiate message Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 08/22] CIFS: Add session setup/logoff capability for SMB2 Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 09/22] CIFS: Add tree connect/disconnect " Pavel Shilovsky
2012-06-19 12:39   ` [PATCH 10/22] CIFS: Process reconnects for SMB2 shares Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 11/22] CIFS: Move getting dfs referalls to ops struct Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 12/22] CIFS: Move informational tcon calls " Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 13/22] CIFS: Move is_path_accessible " Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 14/22] CIFS: Add SMB2 support for is_path_accessible Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 15/22] CIFS: Move query inode info code to ops struct Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 16/22] CIFS: Query SMB2 inode info Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 17/22] CIFS: Move building path to root to ops struct Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 18/22] CIFS: Add SMB2 support for build_path_to_root Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 19/22] CIFS: Move echo code to osp struct Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 20/22] CIFS: Add echo request support for SMB2 Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 21/22] CIFS: Move clear/print_stats code to ops struct Pavel Shilovsky
2012-06-19 12:40   ` [PATCH 22/22] CIFS: Allow SMB2 statistics to be tracked Pavel Shilovsky

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.