diff --git a/src/cm_persist/cm_nvme.cpp b/src/cm_persist/cm_nvme.cpp new file mode 100644 index 0000000..c195833 --- /dev/null +++ b/src/cm_persist/cm_nvme.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2022 Huawei Technologies Co.,Ltd. + * + * CM is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * ------------------------------------------------------------------------- + * + * cm_nvme.cpp + * + * IDENTIFICATION + * src/cm_persist/cm_nvme.cpp + * + * ------------------------------------------------------------------------- + */ +#include "cm_nvme.h" + +#include +#include + +#define CM_DEF_BLOCK_SIZE (512) +#define CM_NVME_SC_SUCCESS 0x0 +#define CM_NVME_ERR_MISCOMPARE (-2) + +typedef enum en_status { + CM_ERROR = -1, + CM_SUCCESS = 0 +} status_t; + +// NVMe vaai compare and write, just support 1 block now +int32 CmNVMeCaw(int32 fd, uint64 blockAddr, char *buff, uint32 buffLen) +{ + int32 status; + struct nvme_user_io io = {0}; + + io.opcode = nvme_cmd_compare; + io.slba = blockAddr; + io.addr = (uint64) buff; + status = ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io); + if (status == CM_NVME_SC_COMPARE_FAILED) { + (void)printf(_("Sending NVMe compare command in caw failed, %s(%#x)."), CmNVMeStatusMessage(status), status); + return CM_NVME_ERR_MISCOMPARE; + } else if (status != CM_NVME_SC_SUCCESS) { + (void)printf(_("Sending NVMe compare command in caw failed, %s(%#x)."), CmNVMeStatusMessage(status), status); + return CM_ERROR; + } + + io.opcode = nvme_cmd_write; + io.addr = (uint64)(buff + CM_DEF_BLOCK_SIZE); + status = ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io); + if (status != CM_NVME_SC_SUCCESS) { + (void)printf(_("Sending NVMe write command in caw failed, %s(%#x)."), CmNVMeStatusMessage(status), status); + return CM_ERROR; + } + + return CM_SUCCESS; +} + +const char* CmNVMeStatusMessage(uint32 status) +{ + switch (status & 0x3ff) { + case CM_NVME_SC_SUCCESS: + return "SUCCESS: The command completed successfully"; + case CM_NVME_SC_INVALID_OPCODE: + return "INVALID_OPCODE: The associated command opcode field is not valid"; + case CM_NVME_SC_INVALID_FIELD: + return "INVALID_FIELD: A reserved coded value or an unsupported value in a defined field"; + case CM_NVME_SC_CMDID_CONFLICT: + return "CMDID_CONFLICT: The command identifier is already in use"; + case CM_NVME_SC_DATA_XFER_ERROR: + return "DATA_XFER_ERROR: Error while trying to transfer the data or metadata"; + case CM_NVME_SC_POWER_LOSS: + return "POWER_LOSS: Command aborted due to power loss notification"; + case CM_NVME_SC_INTERNAL: + return "INTERNAL: The command was not completed successfully due to an internal error"; + case CM_NVME_SC_ABORT_REQ: + return "ABORT_REQ: The command was aborted due to a Command Abort request"; + case CM_NVME_SC_ABORT_QUEUE: + return "ABORT_QUEUE: The command was aborted due to a Delete I/O Submission Queue request"; + case CM_NVME_SC_FUSED_FAIL: + return "FUSED_FAIL: The command was aborted due to the other command in a fused operation failing"; + case CM_NVME_SC_FUSED_MISSING: + return "FUSED_MISSING: The command was aborted due to a Missing Fused Command"; + case CM_NVME_SC_INVALID_NS: + return "INVALID_NS: The namespace or the format of that namespace is invalid"; + case CM_NVME_SC_CMD_SEQ_ERROR: + return "CMD_SEQ_ERROR: The command was aborted due to a protocol violation in a multicommand sequence"; + case CM_NVME_SC_SGL_INVALID_LAST: + return "SGL_INVALID_LAST: The command includes an invalid SGL Last Segment or SGL Segment descriptor."; + case CM_NVME_SC_SGL_INVALID_COUNT: + return "SGL_INVALID_COUNT: There is an SGL Last Segment descriptor or an SGL Segment descriptor in a" + " location other than the last descriptor of a segment based on the length indicated."; + case CM_NVME_SC_SGL_INVALID_DATA: + return "SGL_INVALID_DATA: This may occur if the length of a Data SGL is too short."; + case CM_NVME_SC_SGL_INVALID_METADATA: + return "SGL_INVALID_METADATA: This may occur if the length of a Metadata SGL is too short"; + case CM_NVME_SC_SGL_INVALID_TYPE: + return "SGL_INVALID_TYPE: The type of an SGL Descriptor is a type that is not supported by the controller."; + case CM_NVME_SC_CMB_INVALID_USE: + return "CMB_INVALID_USE: The attempted use of the Controller Memory Buffer is not supported by the controller."; + case CM_NVME_SC_PRP_INVALID_OFFSET: + return "PRP_INVALID_OFFSET: The Offset field for a PRP entry is invalid."; + case CM_NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED: + return "ATOMIC_WRITE_UNIT_EXCEEDED: The length specified exceeds the atomic write unit size."; + case CM_NVME_SC_OPERATION_DENIED: + return "OPERATION_DENIED: The command was denied due to lack of access rights."; + case CM_NVME_SC_SGL_INVALID_OFFSET: + return "SGL_INVALID_OFFSET: The offset specified in a descriptor is invalid."; + case CM_NVME_SC_INCONSISTENT_HOST_ID: + return "INCONSISTENT_HOST_ID: The NVM subsystem detected the simultaneous use of 64-bit and 128-bit Host" + " Identifier values on different controllers."; + case CM_NVME_SC_KEEP_ALIVE_EXPIRED: + return "KEEP_ALIVE_EXPIRED: The Keep Alive Timer expired."; + case CM_NVME_SC_KEEP_ALIVE_INVALID: + return "KEEP_ALIVE_INVALID: The Keep Alive Timeout value specified is invalid."; + case CM_NVME_SC_PREEMPT_ABORT: + return "PREEMPT_ABORT: The command was aborted due to a Reservation Acquire command with the Reservation" + " Acquire Action (RACQA) set to 010b (Preempt and Abort)."; + case CM_NVME_SC_SANITIZE_FAILED: + return "SANITIZE_FAILED: The most recent sanitize operation failed and no recovery actions has been" + " successfully completed"; + case CM_NVME_SC_SANITIZE_IN_PROGRESS: + return "SANITIZE_IN_PROGRESS: The requested function is prohibited while a sanitize operation is in progress"; + case CM_NVME_SC_LBA_RANGE: + return "LBA_RANGE: The command references a LBA that exceeds the size of the namespace"; + case CM_NVME_SC_NS_WRITE_PROTECTED: + return "NS_WRITE_PROTECTED: The command is prohibited while the namespace is write protected by the host."; + case CM_NVME_SC_TRANSIENT_TRANSPORT: + return "TRANSIENT_TRANSPORT: A transient transport error was detected."; + case CM_NVME_SC_CAP_EXCEEDED: + return "CAP_EXCEEDED: The execution of the command has caused the capacity of the namespace to be exceeded"; + case CM_NVME_SC_NS_NOT_READY: + return "NS_NOT_READY: The namespace is not ready to be accessed as a result of a condition other than a" + " condition that is reported as an Asymmetric Namespace Access condition"; + case CM_NVME_SC_RESERVATION_CONFLICT: + return "RESERVATION_CONFLICT: The command was aborted due to a conflict with a reservation held on" + " the accessed namespace"; + case CM_NVME_SC_FORMAT_IN_PROGRESS: + return "FORMAT_IN_PROGRESS: A Format NVM command is in progress on the namespace."; + case CM_NVME_SC_CQ_INVALID: + return "CQ_INVALID: The Completion Queue identifier specified in the command does not exist"; + case CM_NVME_SC_QID_INVALID: + return "QID_INVALID: The creation of the I/O Completion Queue failed due to an invalid queue identifier" + " specified as part of the command. An invalid queue identifier is one that is currently in use" + " or one that is outside the range supported by the controller"; + case CM_NVME_SC_QUEUE_SIZE: + return "QUEUE_SIZE: The host attempted to create an I/O Completion Queue with an invalid number of entries"; + case CM_NVME_SC_ABORT_LIMIT: + return "ABORT_LIMIT: The number of concurrently outstanding Abort commands has exceeded the limit indicated" + " in the Identify Controller data structure"; + case CM_NVME_SC_ABORT_MISSING: + return "ABORT_MISSING: The abort command is missing"; + case CM_NVME_SC_ASYNC_LIMIT: + return "ASYNC_LIMIT: The number of concurrently outstanding Asynchronous Event Request commands" + " has been exceeded"; + case CM_NVME_SC_FIRMWARE_SLOT: + return "FIRMWARE_SLOT: The firmware slot indicated is invalid or read only. This error is indicated if the" + " firmware slot exceeds the number supported"; + case CM_NVME_SC_FIRMWARE_IMAGE: + return "FIRMWARE_IMAGE: The firmware image specified for activation is invalid and not loaded" + " by the controller"; + case CM_NVME_SC_INVALID_VECTOR: + return "INVALID_VECTOR: The creation of the I/O Completion Queue failed due to an invalid interrupt vector" + " specified as part of the command"; + case CM_NVME_SC_INVALID_LOG_PAGE: + return "INVALID_LOG_PAGE: The log page indicated is invalid. This error condition is also returned if a" + " reserved log page is requested"; + case CM_NVME_SC_INVALID_FORMAT: + return "INVALID_FORMAT: The LBA Format specified is not supported. This may be due to various conditions"; + case CM_NVME_SC_FW_NEEDS_CONV_RESET: + return "FW_NEEDS_CONVENTIONAL_RESET: The firmware commit was successful, however, activation of the firmware" + " image requires a conventional reset"; + case CM_NVME_SC_INVALID_QUEUE: + return "INVALID_QUEUE: This error indicates that it is invalid to delete the I/O Completion Queue specified." + " The typical reason for this error condition is that there is an associated I/O Submission Queue" + " that has not been deleted."; + case CM_NVME_SC_FEATURE_NOT_SAVEABLE: + return "FEATURE_NOT_SAVEABLE: The Feature Identifier specified does not support a saveable value"; + case CM_NVME_SC_FEATURE_NOT_CHANGEABLE: + return "FEATURE_NOT_CHANGEABLE: The Feature Identifier is not able to be changed"; + case CM_NVME_SC_FEATURE_NOT_PER_NS: + return "FEATURE_NOT_PER_NS: The Feature Identifier specified is not namespace specific. The Feature Identifier" + " settings apply across all namespaces"; + case CM_NVME_SC_FW_NEEDS_SUBSYS_RESET: + return "FW_NEEDS_SUBSYSTEM_RESET: The firmware commit was successful, however, activation of the firmware image" + " requires an NVM Subsystem"; + case CM_NVME_SC_FW_NEEDS_RESET: + return "FW_NEEDS_RESET: The firmware commit was successful; however, the image specified does not support being" + " activated without a reset"; + case CM_NVME_SC_FW_NEEDS_MAX_TIME: + return "FW_NEEDS_MAX_TIME_VIOLATION: The image specified if activated immediately would exceed" + " the Maximum Time for Firmware Activation (MTFA) value reported in Identify Controller." + " To activate the firmware, the Firmware Commit command needs to be re-issued" + " and the image activated using a reset"; + case CM_NVME_SC_FW_ACTIVATE_PROHIBITED: + return "FW_ACTIVATION_PROHIBITED: The image specified is being prohibited from activation by the controller" + " for vendor specific reasons"; + case CM_NVME_SC_OVERLAPPING_RANGE: + return "OVERLAPPING_RANGE: This error is indicated if the firmware image has overlapping ranges"; + case CM_NVME_SC_NS_INSUFFICIENT_CAP: + return "NS_INSUFFICIENT_CAPACITY: Creating the namespace requires more free space than is currently available." + " The Command Specific Information field of the Error Information Log specifies" + " the total amount of NVM capacity required to create the namespace in bytes"; + case CM_NVME_SC_NS_ID_UNAVAILABLE: + return "NS_ID_UNAVAILABLE: The number of namespaces supported has been exceeded"; + case CM_NVME_SC_NS_ALREADY_ATTACHED: + return "NS_ALREADY_ATTACHED: The controller is already attached to the namespace specified"; + case CM_NVME_SC_NS_IS_PRIVATE: + return "NS_IS_PRIVATE: The namespace is private and is already attached to one controller"; + case CM_NVME_SC_NS_NOT_ATTACHED: + return "NS_NOT_ATTACHED: The request to detach the controller could not be completed because" + " the controller is not attached to the namespace"; + case CM_NVME_SC_THIN_PROV_NOT_SUPP: + return "THIN_PROVISIONING_NOT_SUPPORTED: Thin provisioning is not supported by the controller"; + case CM_NVME_SC_CTRL_LIST_INVALID: + return "CONTROLLER_LIST_INVALID: The controller list provided is invalid"; + case CM_NVME_SC_DEVICE_SELF_TEST_IN_PROGRESS: + return "DEVICE_SELF_TEST_IN_PROGRESS: The controller or NVM subsystem already has" + " a device self-test operation in process."; + case CM_NVME_SC_BP_WRITE_PROHIBITED: + return "BOOT PARTITION WRITE PROHIBITED: The command is trying to modify a Boot Partition while it is locked"; + case CM_NVME_SC_INVALID_CTRL_ID: + return "INVALID_CTRL_ID: An invalid Controller Identifier was specified."; + case CM_NVME_SC_INVALID_SECONDARY_CTRL_STATE: + return "INVALID_SECONDARY_CTRL_STATE: The action requested for the secondary controller is invalid based" + " on the current state of the secondary controller and its primary controller."; + case CM_NVME_SC_INVALID_NUM_CTRL_RESOURCE: + return "INVALID_NUM_CTRL_RESOURCE: The specified number of Flexible Resources is invalid"; + case CM_NVME_SC_INVALID_RESOURCE_ID: + return "INVALID_RESOURCE_ID: At least one of the specified resource identifiers was invalid"; + case CM_NVME_SC_ANA_INVALID_GROUP_ID: + return "ANA_INVALID_GROUP_ID: The specified ANA Group Identifier (ANAGRPID) is not supported" + " in the submitted command."; + case CM_NVME_SC_ANA_ATTACH_FAIL: + return "ANA_ATTACH_FAIL: The controller is not attached to the namespace as a result of an ANA condition"; + case CM_NVME_SC_BAD_ATTRIBUTES: + return "BAD_ATTRIBUTES: Bad attributes were given"; + case CM_NVME_SC_WRITE_FAULT: + return "WRITE_FAULT: The write data could not be committed to the media"; + case CM_NVME_SC_READ_ERROR: + return "READ_ERROR: The read data could not be recovered from the media"; + case CM_NVME_SC_GUARD_CHECK: + return "GUARD_CHECK: The command was aborted due to an end-to-end guard check failure"; + case CM_NVME_SC_APPTAG_CHECK: + return "APPTAG_CHECK: The command was aborted due to an end-to-end application tag check failure"; + case CM_NVME_SC_REFTAG_CHECK: + return "REFTAG_CHECK: The command was aborted due to an end-to-end reference tag check failure"; + case CM_NVME_SC_COMPARE_FAILED: + return "COMPARE_FAILED: The command failed due to a miscompare during a Compare command"; + case CM_NVME_SC_ACCESS_DENIED: + return "ACCESS_DENIED: Access to the namespace and/or LBA range is denied due to lack of access rights"; + case CM_NVME_SC_UNWRITTEN_BLOCK: + return "UNWRITTEN_BLOCK: The command failed due to an attempt to read from an LBA range containing" + " a deallocated or unwritten logical block"; + case CM_NVME_SC_ANA_PERSISTENT_LOSS: + return "ASYMMETRIC_NAMESPACE_ACCESS_PERSISTENT_LOSS: The requested function (e.g., command)" + " is not able to be performed as a result of the relationship between the controller" + " and the namespace being in the ANA Persistent Loss state"; + case CM_NVME_SC_ANA_INACCESSIBLE: + return "ASYMMETRIC_NAMESPACE_ACCESS_INACCESSIBLE: The requested function (e.g., command)" + " is not able to be performed as a result of the relationship between the controller" + " and the namespace being in the ANA Inaccessible state"; + case CM_NVME_SC_ANA_TRANSITION: + return "ASYMMETRIC_NAMESPACE_ACCESS_TRANSITION: The requested function (e.g., command)" + " is not able to be performed as a result of the relationship between the controller" + " and the namespace transitioning between Asymmetric Namespace Access states"; + case CM_NVME_SC_CMD_INTERRUPTED: + return "CMD_INTERRUPTED: Command processing was interrupted and the controller is unable" + " to successfully complete the command. The host should retry the command."; + case CM_NVME_SC_PMR_SAN_PROHIBITED: + return "Sanitize Prohibited While Persistent Memory Region is Enabled: A sanitize operation" + " is prohibited while the Persistent Memory Region is enabled."; + default: + return "Unknown"; + } +} diff --git a/src/cm_persist/share_disk_lock.cpp b/src/cm_persist/share_disk_lock.cpp index 2235557..0552b60 100644 --- a/src/cm_persist/share_disk_lock.cpp +++ b/src/cm_persist/share_disk_lock.cpp @@ -20,6 +20,7 @@ * * ------------------------------------------------------------------------- */ +#include #include #include #include @@ -27,6 +28,9 @@ #include "securec.h" #include "share_disk_lock.h" +#define CM_DISK_PROTOCOL_SCSI3 0 +#define CM_DISK_PROTOCOL_NVME 1 + const int BLOCK_NUMS = 3; const uint32 LOCK_BLOCK_NUMS = 2; const time_t MAX_VALID_LOCK_TIME = 125; @@ -151,10 +155,31 @@ status_t CmDiskLockS(dlock_t *lock, const char *scsiDev, int32 fd) return CM_SUCCESS; } +static cm_disk_caw_hdl_t gCmDiskCawHandle[] = { + { CmScsi3Caw, "Scsi3 caw" }, + { CmNVMeCaw, "NVMe caw" } +}; + +static int32 CmDiskProtocol(int32 fd) +{ + int32 nsid; + int cmDiskProtocol = CM_DISK_PROTOCOL_SCSI3; + + nsid = ioctl(fd, NVME_IOCTL_ID); + if (nsid == -1) { + (void)printf(_("Ioctl get nsid error, errno %d.\n"), errno); + cmDiskProtocol = CM_DISK_PROTOCOL_SCSI3; + } else { + cmDiskProtocol = CM_DISK_PROTOCOL_NVME; + } + + return cmDiskProtocol; +} + int32 CmDiskLock(dlock_t *lock, int32 fd) { uint32 buffLen = LOCK_BLOCK_NUMS * CM_DEF_BLOCK_SIZE; - + int32 cmDiskProtocol = CM_DISK_PROTOCOL_SCSI3; if (lock == NULL || fd < 0) { return -1; } @@ -162,14 +187,15 @@ int32 CmDiskLock(dlock_t *lock, int32 fd) time_t t = time(NULL); LOCKW_LOCK_TIME(*lock) = CalcLockTime(t); LOCKW_LOCK_CREATE_TIME(*lock) = t; - int32 ret = CmScsi3Caw(fd, lock->lockAddr / CM_DEF_BLOCK_SIZE, lock->lockr, buffLen); + cmDiskProtocol = CmDiskProtocol(fd); + int32 ret = gCmDiskCawHandle[cmDiskProtocol].exec(fd, lock->lockAddr / CM_DEF_BLOCK_SIZE, lock->lockr, buffLen); if (ret != (int)CM_SUCCESS) { if (ret != CM_SCSI_ERR_MISCOMPARE) { - (void)printf(_("Scsi3 caw failed, addr %lu.\n"), lock->lockAddr); + (void)printf(_("%s failed, addr %lu.\n"), gCmDiskCawHandle[cmDiskProtocol].desc, lock->lockAddr); return -1; } } else { - (void)printf(_("Scsi3 caw succ.\n")); + (void)printf(_("%s succ.\n"), gCmDiskCawHandle[cmDiskProtocol].desc); return 0; } @@ -182,28 +208,30 @@ int32 CmDiskLock(dlock_t *lock, int32 fd) // if the owner of the lock is zero, we can lock succ LOCKR_INST_ID(*lock) = 0; LOCKW_LOCK_CREATE_TIME(*lock) = LOCKR_LOCK_CREATE_TIME(*lock); - ret = CmScsi3Caw(fd, lock->lockAddr / CM_DEF_BLOCK_SIZE, lock->lockr, buffLen); + ret = gCmDiskCawHandle[cmDiskProtocol].exec(fd, lock->lockAddr / CM_DEF_BLOCK_SIZE, lock->lockr, buffLen); if (ret != (int)CM_SUCCESS) { if (ret != CM_SCSI_ERR_MISCOMPARE) { - (void)printf(_("Scsi3 caw failed after reset, addr %lu.\n"), lock->lockAddr); + (void)printf(_("%s failed after reset, addr %lu.\n"), gCmDiskCawHandle[cmDiskProtocol].desc, + lock->lockAddr); return -1; } } else { - (void)printf(_("Scsi3 caw succ after reset.\n")); + (void)printf(_("%s succ after reset.\n"), gCmDiskCawHandle[cmDiskProtocol].desc); return 0; } // if the owner of the lock on the disk is the current instance, we can lock succ LOCKR_INST_ID(*lock) = LOCKW_INST_ID(*lock); LOCKW_LOCK_CREATE_TIME(*lock) = LOCKR_LOCK_CREATE_TIME(*lock); - ret = CmScsi3Caw(fd, lock->lockAddr / CM_DEF_BLOCK_SIZE, lock->lockr, buffLen); + ret = gCmDiskCawHandle[cmDiskProtocol].exec(fd, lock->lockAddr / CM_DEF_BLOCK_SIZE, lock->lockr, buffLen); if (ret != (int)CM_SUCCESS) { if (ret == CM_SCSI_ERR_MISCOMPARE) { // the lock is hold by another instance LOCKW_LOCK_TIME(*lock) = LOCKR_LOCK_TIME(*lock); return CM_DLOCK_ERR_LOCK_OCCUPIED; } else { - (void)printf(_("Scsi3 caw failed when reset instanceId, addr %lu.\n"), lock->lockAddr); + (void)printf(_("%s failed when reset instanceId, addr %lu.\n"), gCmDiskCawHandle[cmDiskProtocol].desc, + lock->lockAddr); LOCKW_LOCK_TIME(*lock) = LOCKR_LOCK_TIME(*lock); return -1; } diff --git a/src/include/cm/cm_persist/cm_nvme.h b/src/include/cm/cm_persist/cm_nvme.h new file mode 100644 index 0000000..ba3bcc1 --- /dev/null +++ b/src/include/cm/cm_persist/cm_nvme.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021 Huawei Technologies Co.,Ltd. + * + * CM is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * ------------------------------------------------------------------------- + * + * cm_nvme.h + * + * + * IDENTIFICATION + * include/cm/cm_persist/cm_nvme.h + * + * ------------------------------------------------------------------------- + */ +#ifndef CM_NVME_H +#define CM_NVME_H +#define _(x) x + +typedef unsigned char uchar; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned long int uint64; +typedef long int int64; +typedef unsigned int uint32; + +struct nvme_user_io { + uint8 opcode; + uint8 flags; + uint16 control; + uint16 nblocks; + uint16 rsvd; + uint64 metadata; + uint64 addr; + uint64 slba; + uint32 dsmgmt; + uint32 reftag; + uint16 apptag; + uint16 appmask; +}; + +enum { + /* + * Generic Command Status: + */ + CM_NVME_SC_SUCCESS = 0x0, + CM_NVME_SC_INVALID_OPCODE = 0x1, + CM_NVME_SC_INVALID_FIELD = 0x2, + CM_NVME_SC_CMDID_CONFLICT = 0x3, + CM_NVME_SC_DATA_XFER_ERROR = 0x4, + CM_NVME_SC_POWER_LOSS = 0x5, + CM_NVME_SC_INTERNAL = 0x6, + CM_NVME_SC_ABORT_REQ = 0x7, + CM_NVME_SC_ABORT_QUEUE = 0x8, + CM_NVME_SC_FUSED_FAIL = 0x9, + CM_NVME_SC_FUSED_MISSING = 0xa, + CM_NVME_SC_INVALID_NS = 0xb, + CM_NVME_SC_CMD_SEQ_ERROR = 0xc, + CM_NVME_SC_SGL_INVALID_LAST = 0xd, + CM_NVME_SC_SGL_INVALID_COUNT = 0xe, + CM_NVME_SC_SGL_INVALID_DATA = 0xf, + CM_NVME_SC_SGL_INVALID_METADATA = 0x10, + CM_NVME_SC_SGL_INVALID_TYPE = 0x11, + CM_NVME_SC_CMB_INVALID_USE = 0x12, + CM_NVME_SC_PRP_INVALID_OFFSET = 0x13, + CM_NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED = 0x14, + CM_NVME_SC_OPERATION_DENIED = 0x15, + CM_NVME_SC_SGL_INVALID_OFFSET = 0x16, + + CM_NVME_SC_INCONSISTENT_HOST_ID = 0x18, + CM_NVME_SC_KEEP_ALIVE_EXPIRED = 0x19, + CM_NVME_SC_KEEP_ALIVE_INVALID = 0x1A, + CM_NVME_SC_PREEMPT_ABORT = 0x1B, + CM_NVME_SC_SANITIZE_FAILED = 0x1C, + CM_NVME_SC_SANITIZE_IN_PROGRESS = 0x1D, + + CM_NVME_SC_NS_WRITE_PROTECTED = 0x20, + CM_NVME_SC_CMD_INTERRUPTED = 0x21, + CM_NVME_SC_TRANSIENT_TRANSPORT = 0x22, + + CM_NVME_SC_LBA_RANGE = 0x80, + CM_NVME_SC_CAP_EXCEEDED = 0x81, + CM_NVME_SC_NS_NOT_READY = 0x82, + CM_NVME_SC_RESERVATION_CONFLICT = 0x83, + CM_NVME_SC_FORMAT_IN_PROGRESS = 0x84, + + /* + * Command Specific Status: + */ + CM_NVME_SC_CQ_INVALID = 0x100, + CM_NVME_SC_QID_INVALID = 0x101, + CM_NVME_SC_QUEUE_SIZE = 0x102, + CM_NVME_SC_ABORT_LIMIT = 0x103, + CM_NVME_SC_ABORT_MISSING = 0x104, + CM_NVME_SC_ASYNC_LIMIT = 0x105, + CM_NVME_SC_FIRMWARE_SLOT = 0x106, + CM_NVME_SC_FIRMWARE_IMAGE = 0x107, + CM_NVME_SC_INVALID_VECTOR = 0x108, + CM_NVME_SC_INVALID_LOG_PAGE = 0x109, + CM_NVME_SC_INVALID_FORMAT = 0x10a, + CM_NVME_SC_FW_NEEDS_CONV_RESET = 0x10b, + CM_NVME_SC_INVALID_QUEUE = 0x10c, + CM_NVME_SC_FEATURE_NOT_SAVEABLE = 0x10d, + CM_NVME_SC_FEATURE_NOT_CHANGEABLE = 0x10e, + CM_NVME_SC_FEATURE_NOT_PER_NS = 0x10f, + CM_NVME_SC_FW_NEEDS_SUBSYS_RESET = 0x110, + CM_NVME_SC_FW_NEEDS_RESET = 0x111, + CM_NVME_SC_FW_NEEDS_MAX_TIME = 0x112, + CM_NVME_SC_FW_ACTIVATE_PROHIBITED = 0x113, + CM_NVME_SC_OVERLAPPING_RANGE = 0x114, + CM_NVME_SC_NS_INSUFFICIENT_CAP = 0x115, + CM_NVME_SC_NS_ID_UNAVAILABLE = 0x116, + CM_NVME_SC_NS_ALREADY_ATTACHED = 0x118, + CM_NVME_SC_NS_IS_PRIVATE = 0x119, + CM_NVME_SC_NS_NOT_ATTACHED = 0x11a, + CM_NVME_SC_THIN_PROV_NOT_SUPP = 0x11b, + CM_NVME_SC_CTRL_LIST_INVALID = 0x11c, + CM_NVME_SC_DEVICE_SELF_TEST_IN_PROGRESS = 0x11d, + CM_NVME_SC_BP_WRITE_PROHIBITED = 0x11e, + CM_NVME_SC_INVALID_CTRL_ID = 0x11f, + CM_NVME_SC_INVALID_SECONDARY_CTRL_STATE = 0x120, + CM_NVME_SC_INVALID_NUM_CTRL_RESOURCE = 0x121, + CM_NVME_SC_INVALID_RESOURCE_ID = 0x122, + CM_NVME_SC_PMR_SAN_PROHIBITED = 0x123, + CM_NVME_SC_ANA_INVALID_GROUP_ID = 0x124, + CM_NVME_SC_ANA_ATTACH_FAIL = 0x125, + + /* + * I/O Command Set Specific - NVM commands: + */ + CM_NVME_SC_BAD_ATTRIBUTES = 0x180, + CM_NVME_SC_INVALID_PI = 0x181, + CM_NVME_SC_READ_ONLY = 0x182, + CM_NVME_SC_ONCS_NOT_SUPPORTED = 0x183, + + /* + * I/O Command Set Specific - Fabrics commands: + */ + CM_NVME_SC_CONNECT_FORMAT = 0x180, + CM_NVME_SC_CONNECT_CTRL_BUSY = 0x181, + CM_NVME_SC_CONNECT_INVALID_PARAM = 0x182, + CM_NVME_SC_CONNECT_RESTART_DISC = 0x183, + CM_NVME_SC_CONNECT_INVALID_HOST = 0x184, + + CM_NVME_SC_DISCOVERY_RESTART = 0x190, + CM_NVME_SC_AUTH_REQUIRED = 0x191, + + /* + * Media and Data Integrity Errors: + */ + CM_NVME_SC_WRITE_FAULT = 0x280, + CM_NVME_SC_READ_ERROR = 0x281, + CM_NVME_SC_GUARD_CHECK = 0x282, + CM_NVME_SC_APPTAG_CHECK = 0x283, + CM_NVME_SC_REFTAG_CHECK = 0x284, + CM_NVME_SC_COMPARE_FAILED = 0x285, + CM_NVME_SC_ACCESS_DENIED = 0x286, + CM_NVME_SC_UNWRITTEN_BLOCK = 0x287, + + /* + * Path-related Errors: + */ + CM_NVME_SC_ANA_PERSISTENT_LOSS = 0x301, + CM_NVME_SC_ANA_INACCESSIBLE = 0x302, + CM_NVME_SC_ANA_TRANSITION = 0x303, + + CM_NVME_SC_CRD = 0x1800, + CM_NVME_SC_DNR = 0x4000, +}; + + +#define nvme_cmd_write 0x01 +#define nvme_cmd_compare 0x05 + +#define NVME_IOCTL_ID _IO('N', 0x40) +#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) + +int32 CmNVMeCaw(int32 fd, uint64 blockAddr, char *buff, uint32 buffLen); +const char* CmNVMeStatusMessage(uint32 status); +#endif diff --git a/src/include/cm/cm_persist/share_disk_lock.h b/src/include/cm/cm_persist/share_disk_lock.h index 18c64f6..3b891eb 100644 --- a/src/include/cm/cm_persist/share_disk_lock.h +++ b/src/include/cm/cm_persist/share_disk_lock.h @@ -24,8 +24,10 @@ #ifndef CM_DISK_LOCK_H #define CM_DISK_LOCK_H #include +#include "cm_nvme.h" #include "cm_scsi.h" + #define DISK_LOCK_HEADER_MAGIC (0x3847EEFFFFEE3847) #define DISK_DEFAULT_LOCK_INTERVAL (100) #define DISK_LOCK_ALIGN_SIZE_512 (512) @@ -106,4 +108,11 @@ status_t CmDiskLockS(dlock_t *lock, const char *scsiDev, int32 fd); int32 CmDiskLock(dlock_t *lock, int32 fd); status_t CmDiskLockf(dlock_t *lock, int32 fd, int64 lockTime); status_t CmGetDlockInfo(dlock_t *lock, int32 fd); + +typedef int32 (*CmDiskCaw)(int32 fd, uint64 blockAddr, char *buff, uint32 buffLen); +typedef struct st_cm_disk_caw_hdl { + CmDiskCaw exec; + char * desc; +} cm_disk_caw_hdl_t; + #endif