disk_linux.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. // +build linux
  2. package disk
  3. import (
  4. "bufio"
  5. "bytes"
  6. "context"
  7. "fmt"
  8. "io/ioutil"
  9. "path/filepath"
  10. "strconv"
  11. "strings"
  12. "golang.org/x/sys/unix"
  13. "github.com/shirou/gopsutil/internal/common"
  14. )
  15. const (
  16. SectorSize = 512
  17. )
  18. const (
  19. // man statfs
  20. ADFS_SUPER_MAGIC = 0xadf5
  21. AFFS_SUPER_MAGIC = 0xADFF
  22. BDEVFS_MAGIC = 0x62646576
  23. BEFS_SUPER_MAGIC = 0x42465331
  24. BFS_MAGIC = 0x1BADFACE
  25. BINFMTFS_MAGIC = 0x42494e4d
  26. BTRFS_SUPER_MAGIC = 0x9123683E
  27. CGROUP_SUPER_MAGIC = 0x27e0eb
  28. CIFS_MAGIC_NUMBER = 0xFF534D42
  29. CODA_SUPER_MAGIC = 0x73757245
  30. COH_SUPER_MAGIC = 0x012FF7B7
  31. CRAMFS_MAGIC = 0x28cd3d45
  32. DEBUGFS_MAGIC = 0x64626720
  33. DEVFS_SUPER_MAGIC = 0x1373
  34. DEVPTS_SUPER_MAGIC = 0x1cd1
  35. EFIVARFS_MAGIC = 0xde5e81e4
  36. EFS_SUPER_MAGIC = 0x00414A53
  37. EXT_SUPER_MAGIC = 0x137D
  38. EXT2_OLD_SUPER_MAGIC = 0xEF51
  39. EXT2_SUPER_MAGIC = 0xEF53
  40. EXT3_SUPER_MAGIC = 0xEF53
  41. EXT4_SUPER_MAGIC = 0xEF53
  42. FUSE_SUPER_MAGIC = 0x65735546
  43. FUTEXFS_SUPER_MAGIC = 0xBAD1DEA
  44. HFS_SUPER_MAGIC = 0x4244
  45. HOSTFS_SUPER_MAGIC = 0x00c0ffee
  46. HPFS_SUPER_MAGIC = 0xF995E849
  47. HUGETLBFS_MAGIC = 0x958458f6
  48. ISOFS_SUPER_MAGIC = 0x9660
  49. JFFS2_SUPER_MAGIC = 0x72b6
  50. JFS_SUPER_MAGIC = 0x3153464a
  51. MINIX_SUPER_MAGIC = 0x137F /* orig. minix */
  52. MINIX_SUPER_MAGIC2 = 0x138F /* 30 char minix */
  53. MINIX2_SUPER_MAGIC = 0x2468 /* minix V2 */
  54. MINIX2_SUPER_MAGIC2 = 0x2478 /* minix V2, 30 char names */
  55. MINIX3_SUPER_MAGIC = 0x4d5a /* minix V3 fs, 60 char names */
  56. MQUEUE_MAGIC = 0x19800202
  57. MSDOS_SUPER_MAGIC = 0x4d44
  58. NCP_SUPER_MAGIC = 0x564c
  59. NFS_SUPER_MAGIC = 0x6969
  60. NILFS_SUPER_MAGIC = 0x3434
  61. NTFS_SB_MAGIC = 0x5346544e
  62. OCFS2_SUPER_MAGIC = 0x7461636f
  63. OPENPROM_SUPER_MAGIC = 0x9fa1
  64. PIPEFS_MAGIC = 0x50495045
  65. PROC_SUPER_MAGIC = 0x9fa0
  66. PSTOREFS_MAGIC = 0x6165676C
  67. QNX4_SUPER_MAGIC = 0x002f
  68. QNX6_SUPER_MAGIC = 0x68191122
  69. RAMFS_MAGIC = 0x858458f6
  70. REISERFS_SUPER_MAGIC = 0x52654973
  71. ROMFS_MAGIC = 0x7275
  72. SELINUX_MAGIC = 0xf97cff8c
  73. SMACK_MAGIC = 0x43415d53
  74. SMB_SUPER_MAGIC = 0x517B
  75. SOCKFS_MAGIC = 0x534F434B
  76. SQUASHFS_MAGIC = 0x73717368
  77. SYSFS_MAGIC = 0x62656572
  78. SYSV2_SUPER_MAGIC = 0x012FF7B6
  79. SYSV4_SUPER_MAGIC = 0x012FF7B5
  80. TMPFS_MAGIC = 0x01021994
  81. UDF_SUPER_MAGIC = 0x15013346
  82. UFS_MAGIC = 0x00011954
  83. USBDEVICE_SUPER_MAGIC = 0x9fa2
  84. V9FS_MAGIC = 0x01021997
  85. VXFS_SUPER_MAGIC = 0xa501FCF5
  86. XENFS_SUPER_MAGIC = 0xabba1974
  87. XENIX_SUPER_MAGIC = 0x012FF7B4
  88. XFS_SUPER_MAGIC = 0x58465342
  89. _XIAFS_SUPER_MAGIC = 0x012FD16D
  90. AFS_SUPER_MAGIC = 0x5346414F
  91. AUFS_SUPER_MAGIC = 0x61756673
  92. ANON_INODE_FS_SUPER_MAGIC = 0x09041934
  93. CEPH_SUPER_MAGIC = 0x00C36400
  94. ECRYPTFS_SUPER_MAGIC = 0xF15F
  95. FAT_SUPER_MAGIC = 0x4006
  96. FHGFS_SUPER_MAGIC = 0x19830326
  97. FUSEBLK_SUPER_MAGIC = 0x65735546
  98. FUSECTL_SUPER_MAGIC = 0x65735543
  99. GFS_SUPER_MAGIC = 0x1161970
  100. GPFS_SUPER_MAGIC = 0x47504653
  101. MTD_INODE_FS_SUPER_MAGIC = 0x11307854
  102. INOTIFYFS_SUPER_MAGIC = 0x2BAD1DEA
  103. ISOFS_R_WIN_SUPER_MAGIC = 0x4004
  104. ISOFS_WIN_SUPER_MAGIC = 0x4000
  105. JFFS_SUPER_MAGIC = 0x07C0
  106. KAFS_SUPER_MAGIC = 0x6B414653
  107. LUSTRE_SUPER_MAGIC = 0x0BD00BD0
  108. NFSD_SUPER_MAGIC = 0x6E667364
  109. PANFS_SUPER_MAGIC = 0xAAD7AAEA
  110. RPC_PIPEFS_SUPER_MAGIC = 0x67596969
  111. SECURITYFS_SUPER_MAGIC = 0x73636673
  112. UFS_BYTESWAPPED_SUPER_MAGIC = 0x54190100
  113. VMHGFS_SUPER_MAGIC = 0xBACBACBC
  114. VZFS_SUPER_MAGIC = 0x565A4653
  115. ZFS_SUPER_MAGIC = 0x2FC12FC1
  116. )
  117. // coreutils/src/stat.c
  118. var fsTypeMap = map[int64]string{
  119. ADFS_SUPER_MAGIC: "adfs", /* 0xADF5 local */
  120. AFFS_SUPER_MAGIC: "affs", /* 0xADFF local */
  121. AFS_SUPER_MAGIC: "afs", /* 0x5346414F remote */
  122. ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */
  123. AUFS_SUPER_MAGIC: "aufs", /* 0x61756673 remote */
  124. // AUTOFS_SUPER_MAGIC: "autofs", /* 0x0187 local */
  125. BEFS_SUPER_MAGIC: "befs", /* 0x42465331 local */
  126. BDEVFS_MAGIC: "bdevfs", /* 0x62646576 local */
  127. BFS_MAGIC: "bfs", /* 0x1BADFACE local */
  128. BINFMTFS_MAGIC: "binfmt_misc", /* 0x42494E4D local */
  129. BTRFS_SUPER_MAGIC: "btrfs", /* 0x9123683E local */
  130. CEPH_SUPER_MAGIC: "ceph", /* 0x00C36400 remote */
  131. CGROUP_SUPER_MAGIC: "cgroupfs", /* 0x0027E0EB local */
  132. CIFS_MAGIC_NUMBER: "cifs", /* 0xFF534D42 remote */
  133. CODA_SUPER_MAGIC: "coda", /* 0x73757245 remote */
  134. COH_SUPER_MAGIC: "coh", /* 0x012FF7B7 local */
  135. CRAMFS_MAGIC: "cramfs", /* 0x28CD3D45 local */
  136. DEBUGFS_MAGIC: "debugfs", /* 0x64626720 local */
  137. DEVFS_SUPER_MAGIC: "devfs", /* 0x1373 local */
  138. DEVPTS_SUPER_MAGIC: "devpts", /* 0x1CD1 local */
  139. ECRYPTFS_SUPER_MAGIC: "ecryptfs", /* 0xF15F local */
  140. EFS_SUPER_MAGIC: "efs", /* 0x00414A53 local */
  141. EXT_SUPER_MAGIC: "ext", /* 0x137D local */
  142. EXT2_SUPER_MAGIC: "ext2/ext3", /* 0xEF53 local */
  143. EXT2_OLD_SUPER_MAGIC: "ext2", /* 0xEF51 local */
  144. FAT_SUPER_MAGIC: "fat", /* 0x4006 local */
  145. FHGFS_SUPER_MAGIC: "fhgfs", /* 0x19830326 remote */
  146. FUSEBLK_SUPER_MAGIC: "fuseblk", /* 0x65735546 remote */
  147. FUSECTL_SUPER_MAGIC: "fusectl", /* 0x65735543 remote */
  148. FUTEXFS_SUPER_MAGIC: "futexfs", /* 0x0BAD1DEA local */
  149. GFS_SUPER_MAGIC: "gfs/gfs2", /* 0x1161970 remote */
  150. GPFS_SUPER_MAGIC: "gpfs", /* 0x47504653 remote */
  151. HFS_SUPER_MAGIC: "hfs", /* 0x4244 local */
  152. HPFS_SUPER_MAGIC: "hpfs", /* 0xF995E849 local */
  153. HUGETLBFS_MAGIC: "hugetlbfs", /* 0x958458F6 local */
  154. MTD_INODE_FS_SUPER_MAGIC: "inodefs", /* 0x11307854 local */
  155. INOTIFYFS_SUPER_MAGIC: "inotifyfs", /* 0x2BAD1DEA local */
  156. ISOFS_SUPER_MAGIC: "isofs", /* 0x9660 local */
  157. ISOFS_R_WIN_SUPER_MAGIC: "isofs", /* 0x4004 local */
  158. ISOFS_WIN_SUPER_MAGIC: "isofs", /* 0x4000 local */
  159. JFFS_SUPER_MAGIC: "jffs", /* 0x07C0 local */
  160. JFFS2_SUPER_MAGIC: "jffs2", /* 0x72B6 local */
  161. JFS_SUPER_MAGIC: "jfs", /* 0x3153464A local */
  162. KAFS_SUPER_MAGIC: "k-afs", /* 0x6B414653 remote */
  163. LUSTRE_SUPER_MAGIC: "lustre", /* 0x0BD00BD0 remote */
  164. MINIX_SUPER_MAGIC: "minix", /* 0x137F local */
  165. MINIX_SUPER_MAGIC2: "minix (30 char.)", /* 0x138F local */
  166. MINIX2_SUPER_MAGIC: "minix v2", /* 0x2468 local */
  167. MINIX2_SUPER_MAGIC2: "minix v2 (30 char.)", /* 0x2478 local */
  168. MINIX3_SUPER_MAGIC: "minix3", /* 0x4D5A local */
  169. MQUEUE_MAGIC: "mqueue", /* 0x19800202 local */
  170. MSDOS_SUPER_MAGIC: "msdos", /* 0x4D44 local */
  171. NCP_SUPER_MAGIC: "novell", /* 0x564C remote */
  172. NFS_SUPER_MAGIC: "nfs", /* 0x6969 remote */
  173. NFSD_SUPER_MAGIC: "nfsd", /* 0x6E667364 remote */
  174. NILFS_SUPER_MAGIC: "nilfs", /* 0x3434 local */
  175. NTFS_SB_MAGIC: "ntfs", /* 0x5346544E local */
  176. OPENPROM_SUPER_MAGIC: "openprom", /* 0x9FA1 local */
  177. OCFS2_SUPER_MAGIC: "ocfs2", /* 0x7461636f remote */
  178. PANFS_SUPER_MAGIC: "panfs", /* 0xAAD7AAEA remote */
  179. PIPEFS_MAGIC: "pipefs", /* 0x50495045 remote */
  180. PROC_SUPER_MAGIC: "proc", /* 0x9FA0 local */
  181. PSTOREFS_MAGIC: "pstorefs", /* 0x6165676C local */
  182. QNX4_SUPER_MAGIC: "qnx4", /* 0x002F local */
  183. QNX6_SUPER_MAGIC: "qnx6", /* 0x68191122 local */
  184. RAMFS_MAGIC: "ramfs", /* 0x858458F6 local */
  185. REISERFS_SUPER_MAGIC: "reiserfs", /* 0x52654973 local */
  186. ROMFS_MAGIC: "romfs", /* 0x7275 local */
  187. RPC_PIPEFS_SUPER_MAGIC: "rpc_pipefs", /* 0x67596969 local */
  188. SECURITYFS_SUPER_MAGIC: "securityfs", /* 0x73636673 local */
  189. SELINUX_MAGIC: "selinux", /* 0xF97CFF8C local */
  190. SMB_SUPER_MAGIC: "smb", /* 0x517B remote */
  191. SOCKFS_MAGIC: "sockfs", /* 0x534F434B local */
  192. SQUASHFS_MAGIC: "squashfs", /* 0x73717368 local */
  193. SYSFS_MAGIC: "sysfs", /* 0x62656572 local */
  194. SYSV2_SUPER_MAGIC: "sysv2", /* 0x012FF7B6 local */
  195. SYSV4_SUPER_MAGIC: "sysv4", /* 0x012FF7B5 local */
  196. TMPFS_MAGIC: "tmpfs", /* 0x01021994 local */
  197. UDF_SUPER_MAGIC: "udf", /* 0x15013346 local */
  198. UFS_MAGIC: "ufs", /* 0x00011954 local */
  199. UFS_BYTESWAPPED_SUPER_MAGIC: "ufs", /* 0x54190100 local */
  200. USBDEVICE_SUPER_MAGIC: "usbdevfs", /* 0x9FA2 local */
  201. V9FS_MAGIC: "v9fs", /* 0x01021997 local */
  202. VMHGFS_SUPER_MAGIC: "vmhgfs", /* 0xBACBACBC remote */
  203. VXFS_SUPER_MAGIC: "vxfs", /* 0xA501FCF5 local */
  204. VZFS_SUPER_MAGIC: "vzfs", /* 0x565A4653 local */
  205. XENFS_SUPER_MAGIC: "xenfs", /* 0xABBA1974 local */
  206. XENIX_SUPER_MAGIC: "xenix", /* 0x012FF7B4 local */
  207. XFS_SUPER_MAGIC: "xfs", /* 0x58465342 local */
  208. _XIAFS_SUPER_MAGIC: "xia", /* 0x012FD16D local */
  209. ZFS_SUPER_MAGIC: "zfs", /* 0x2FC12FC1 local */
  210. }
  211. // Partitions returns disk partitions. If all is false, returns
  212. // physical devices only (e.g. hard disks, cd-rom drives, USB keys)
  213. // and ignore all others (e.g. memory partitions such as /dev/shm)
  214. func Partitions(all bool) ([]PartitionStat, error) {
  215. return PartitionsWithContext(context.Background(), all)
  216. }
  217. func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
  218. filename := common.HostProc("self/mounts")
  219. lines, err := common.ReadLines(filename)
  220. if err != nil {
  221. return nil, err
  222. }
  223. fs, err := getFileSystems()
  224. if err != nil {
  225. return nil, err
  226. }
  227. ret := make([]PartitionStat, 0, len(lines))
  228. for _, line := range lines {
  229. fields := strings.Fields(line)
  230. d := PartitionStat{
  231. Device: fields[0],
  232. Mountpoint: fields[1],
  233. Fstype: fields[2],
  234. Opts: fields[3],
  235. }
  236. if all == false {
  237. if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
  238. continue
  239. }
  240. }
  241. ret = append(ret, d)
  242. }
  243. return ret, nil
  244. }
  245. // getFileSystems returns supported filesystems from /proc/filesystems
  246. func getFileSystems() ([]string, error) {
  247. filename := common.HostProc("filesystems")
  248. lines, err := common.ReadLines(filename)
  249. if err != nil {
  250. return nil, err
  251. }
  252. var ret []string
  253. for _, line := range lines {
  254. if !strings.HasPrefix(line, "nodev") {
  255. ret = append(ret, strings.TrimSpace(line))
  256. continue
  257. }
  258. t := strings.Split(line, "\t")
  259. if len(t) != 2 || t[1] != "zfs" {
  260. continue
  261. }
  262. ret = append(ret, strings.TrimSpace(t[1]))
  263. }
  264. return ret, nil
  265. }
  266. func IOCounters(names ...string) (map[string]IOCountersStat, error) {
  267. return IOCountersWithContext(context.Background(), names...)
  268. }
  269. func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
  270. filename := common.HostProc("diskstats")
  271. lines, err := common.ReadLines(filename)
  272. if err != nil {
  273. return nil, err
  274. }
  275. ret := make(map[string]IOCountersStat, 0)
  276. empty := IOCountersStat{}
  277. // use only basename such as "/dev/sda1" to "sda1"
  278. for i, name := range names {
  279. names[i] = filepath.Base(name)
  280. }
  281. for _, line := range lines {
  282. fields := strings.Fields(line)
  283. if len(fields) < 14 {
  284. // malformed line in /proc/diskstats, avoid panic by ignoring.
  285. continue
  286. }
  287. name := fields[2]
  288. if len(names) > 0 && !common.StringsHas(names, name) {
  289. continue
  290. }
  291. reads, err := strconv.ParseUint((fields[3]), 10, 64)
  292. if err != nil {
  293. return ret, err
  294. }
  295. mergedReads, err := strconv.ParseUint((fields[4]), 10, 64)
  296. if err != nil {
  297. return ret, err
  298. }
  299. rbytes, err := strconv.ParseUint((fields[5]), 10, 64)
  300. if err != nil {
  301. return ret, err
  302. }
  303. rtime, err := strconv.ParseUint((fields[6]), 10, 64)
  304. if err != nil {
  305. return ret, err
  306. }
  307. writes, err := strconv.ParseUint((fields[7]), 10, 64)
  308. if err != nil {
  309. return ret, err
  310. }
  311. mergedWrites, err := strconv.ParseUint((fields[8]), 10, 64)
  312. if err != nil {
  313. return ret, err
  314. }
  315. wbytes, err := strconv.ParseUint((fields[9]), 10, 64)
  316. if err != nil {
  317. return ret, err
  318. }
  319. wtime, err := strconv.ParseUint((fields[10]), 10, 64)
  320. if err != nil {
  321. return ret, err
  322. }
  323. iopsInProgress, err := strconv.ParseUint((fields[11]), 10, 64)
  324. if err != nil {
  325. return ret, err
  326. }
  327. iotime, err := strconv.ParseUint((fields[12]), 10, 64)
  328. if err != nil {
  329. return ret, err
  330. }
  331. weightedIO, err := strconv.ParseUint((fields[13]), 10, 64)
  332. if err != nil {
  333. return ret, err
  334. }
  335. d := IOCountersStat{
  336. ReadBytes: rbytes * SectorSize,
  337. WriteBytes: wbytes * SectorSize,
  338. ReadCount: reads,
  339. WriteCount: writes,
  340. MergedReadCount: mergedReads,
  341. MergedWriteCount: mergedWrites,
  342. ReadTime: rtime,
  343. WriteTime: wtime,
  344. IopsInProgress: iopsInProgress,
  345. IoTime: iotime,
  346. WeightedIO: weightedIO,
  347. }
  348. if d == empty {
  349. continue
  350. }
  351. d.Name = name
  352. d.SerialNumber = GetDiskSerialNumber(name)
  353. d.Label = GetLabel(name)
  354. ret[name] = d
  355. }
  356. return ret, nil
  357. }
  358. // GetDiskSerialNumber returns Serial Number of given device or empty string
  359. // on error. Name of device is expected, eg. /dev/sda
  360. func GetDiskSerialNumber(name string) string {
  361. return GetDiskSerialNumberWithContext(context.Background(), name)
  362. }
  363. func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
  364. var stat unix.Stat_t
  365. err := unix.Stat(name, &stat)
  366. if err != nil {
  367. return ""
  368. }
  369. major := unix.Major(uint64(stat.Rdev))
  370. minor := unix.Minor(uint64(stat.Rdev))
  371. // Try to get the serial from udev data
  372. udevDataPath := common.HostRun(fmt.Sprintf("udev/data/b%d:%d", major, minor))
  373. if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
  374. scanner := bufio.NewScanner(bytes.NewReader(udevdata))
  375. for scanner.Scan() {
  376. values := strings.Split(scanner.Text(), "=")
  377. if len(values) == 2 && values[0] == "E:ID_SERIAL" {
  378. return values[1]
  379. }
  380. }
  381. }
  382. // Try to get the serial from sysfs, look at the disk device (minor 0) directly
  383. // because if it is a partition it is not going to contain any device information
  384. devicePath := common.HostSys(fmt.Sprintf("dev/block/%d:0/device", major))
  385. model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
  386. serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
  387. if len(model) > 0 && len(serial) > 0 {
  388. return fmt.Sprintf("%s_%s", string(model), string(serial))
  389. }
  390. return ""
  391. }
  392. // GetLabel returns label of given device or empty string on error.
  393. // Name of device is expected, eg. /dev/sda
  394. // Supports label based on devicemapper name
  395. // See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
  396. func GetLabel(name string) string {
  397. // Try label based on devicemapper name
  398. dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
  399. if !common.PathExists(dmname_filename) {
  400. return ""
  401. }
  402. dmname, err := ioutil.ReadFile(dmname_filename)
  403. if err != nil {
  404. return ""
  405. } else {
  406. return string(dmname)
  407. }
  408. }
  409. func getFsType(stat unix.Statfs_t) string {
  410. t := int64(stat.Type)
  411. ret, ok := fsTypeMap[t]
  412. if !ok {
  413. return ""
  414. }
  415. return ret
  416. }