Advertisement
Guest User

Untitled

a guest
Jun 24th, 2019
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.45 KB | None | 0 0
  1. NVME_ADMIN_IDENTIFY = 0x06
  2. NVME_IOCTL_ADMIN_CMD = 0xC0484E41
  3. AMZN_NVME_VID = 0x1D0F
  4. AMZN_NVME_EBS_MN = "Amazon Elastic Block Store"
  5.  
  6. NVME_IDENTIFY_CONTROLLER_PSD = [0, 0, 0, 0, 0, 0, 0, 0, " "].pack("SSLLCCCCa16")
  7. NVME_IDENTIFY_CONTROLLER_AMZN_VS = [" ", " "].pack("a32a#{1024 - 32}")
  8.  
  9. NVME_ADMIN_CMD_TMPL = [
  10. "C", # ("opcode", c_uint8), # op code
  11. "C", # ("flags", c_uint8), # fused operation
  12. "S", # ("cid", c_uint16), # command id
  13. "L", # ("nsid", c_uint32), # namespace id
  14. "Q", # ("reserved0", c_uint64),
  15. "P", # ("mptr", c_uint64), # metadata pointer
  16. "P", # ("addr", c_uint64), # data pointer
  17. "L", # ("mlen", c_uint32), # metadata length
  18. "L", # ("alen", c_uint32), # data length
  19. "L", # ("cdw10", c_uint32),
  20. "L", # ("cdw11", c_uint32),
  21. "L", # ("cdw12", c_uint32),
  22. "L", # ("cdw13", c_uint32),
  23. "L", # ("cdw14", c_uint32),
  24. "L", # ("cdw15", c_uint32),
  25. "Q", # ("reserved1", c_uint64)]
  26. ].join
  27.  
  28. NVME_ID_CTRL_TMPL = [
  29. "S", # ("vid", c_uint16), # PCI Vendor ID
  30. "S", # ("ssvid", c_uint16), # PCI Subsystem Vendor ID
  31. "a20", # ("sn", c_char * 20), # Serial Number
  32. "a40", # ("mn", c_char * 40), # Module Number
  33. "a8", # ("fr", c_char * 8), # Firmware Revision
  34. "C", # ("rab", c_uint8), # Recommend Arbitration Burst
  35. "a3", # ("ieee", c_uint8 * 3), # IEEE OUI Identifier
  36. "C", # ("mic", c_uint8), # Multi-Interface Capabilities
  37. "C", # ("mdts", c_uint8), # Maximum Data Transfer Size
  38. "a#{256 - 78}", # ("reserved0", c_uint8 * (256 - 78)),
  39. "S", # ("oacs", c_uint16), # Optional Admin Command Support
  40. "C", # ("acl", c_uint8), # Abort Command Limit
  41. "C", # ("aerl", c_uint8), # Asynchronous Event Request Limit
  42. "C", # ("frmw", c_uint8), # Firmware Updates
  43. "C", # ("lpa", c_uint8), # Log Page Attributes
  44. "C", # ("elpe", c_uint8), # Error Log Page Entries
  45. "C", # ("npss", c_uint8), # Number of Power States Support
  46. "C", # ("avscc", c_uint8), # Admin Vendor Specific Command Configuration
  47. "a#{512 - 265}", # ("reserved1", c_uint8 * (512 - 265)),
  48. "C", # ("sqes", c_uint8), # Submission Queue Entry Size
  49. "C", # ("cqes", c_uint8), # Completion Queue Entry Size
  50. "S", # ("reserved2", c_uint16),
  51. "L", # ("nn", c_uint32), # Number of Namespaces
  52. "S", # ("oncs", c_uint16), # Optional NVM Command Support
  53. "S", # ("fuses", c_uint16), # Fused Operation Support
  54. "C", # ("fna", c_uint8), # Format NVM Attributes
  55. "C", # ("vwc", c_uint8), # Volatile Write Cache
  56. "S", # ("awun", c_uint16), # Atomic Write Unit Normal
  57. "S", # ("awupf", c_uint16), # Atomic Write Unit Power Fail
  58. "C", # ("nvscc", c_uint8), # NVM Vendor Specific Command Configuration
  59. "a#{704 - 531}", # ("reserved3", c_uint8 * (704 - 531)),
  60. "a#{2048 - 704}", # ("reserved4", c_uint8 * (2048 - 704)),
  61. "a#{NVME_IDENTIFY_CONTROLLER_PSD.size * 32}", # ("psd", nvme_identify_controller_psd * 32), # Power State Descriptor
  62. "a#{NVME_IDENTIFY_CONTROLLER_AMZN_VS.size}", # ("vs", nvme_identify_controller_amzn_vs)] # Vendor Specific
  63. ].join
  64.  
  65. # allocate 4K of memory for nvme_id_ctrl struct (see <linux/nvme.h>)
  66. nvme_id_ctrl_buf = ' ' * 4096
  67.  
  68. NVME_ADMIN_COMMAND = [
  69. NVME_ADMIN_IDENTIFY, # opcode
  70. 0,
  71. 0,
  72. 0,
  73. 0,
  74. " ",
  75. nvme_id_ctrl_buf, # pass pointer to the buffer
  76. # where nvme_id_ctrl struct will be stored
  77. 0,
  78. nvme_id_ctrl_buf.size, # pass size of the buffer
  79. 1,
  80. 0,
  81. 0,
  82. 0,
  83. 0,
  84. 0,
  85. 0
  86. ].pack(NVME_ADMIN_CMD_TMPL) # make binary sequence
  87.  
  88. def nvme_ioctl!(buf, device_path)
  89. File.open(device_path, "r") do |f|
  90. # call `ioctl` system call via ruby's `ioctl` wrapper
  91. # the first arg is the request code, the second is untyped pointer to memory
  92. f.ioctl(NVME_IOCTL_ADMIN_CMD, NVME_ADMIN_COMMAND)
  93. end
  94.  
  95. buf.unpack(NVME_ID_CTRL_TMPL)
  96. end
  97.  
  98. Facter.add(:nvme_device_name_map) do
  99. setcode do
  100. device_map = {}
  101.  
  102. # for each block device which matches glob pattern
  103. Dir.glob("/dev/nvme[0-9]{[0-9],}") { |device|
  104. nvme_id_ctrl_struct = nvme_ioctl!(nvme_id_ctrl_buf, device)
  105.  
  106. if nvme_id_ctrl_struct[0] == AMZN_NVME_VID or nvme_id_ctrl_struct[3] == AMZN_NVME_EBS_MN
  107. # amazon device name is a 33th element of array
  108. # the former 32 bytes are a device name, the latter bytes are reserved
  109. device_name = nvme_id_ctrl_struct[33].strip
  110.  
  111. # prepend "/dev/" if for some reason amazon desided to trim it before
  112. device_name = "/dev/" + device_name if not device_name.start_with?("/dev/")
  113.  
  114. # we are interested in block devices which are named like nvme1n1
  115. # and not in nvme1 which is nvme subsystem
  116. device_map[device_name] = device + "n1"
  117. end
  118. }
  119.  
  120. # puppet facts find | jq '.. | .nvme_device_name_map? | select(. != null)'
  121. # {
  122. # "/dev/xvdf": "/dev/nvme1n1",
  123. # "/dev/xvdh": "/dev/nvme3n1",
  124. # "/dev/xvdg": "/dev/nvme2n1",
  125. # "sda1": "/dev/nvme0n1"
  126. # }
  127. device_map
  128. end
  129. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement