disk_linux.go 19 KB

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