Coverage Report

Created: 2025-06-13 06:36

/src/util-linux/libblkid/src/topology/sysfs.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * sysfs based topology -- gathers topology information from Linux sysfs
3
 *
4
 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
5
 *
6
 * This file may be redistributed under the terms of the
7
 * GNU Lesser General Public License.
8
 *
9
 * For more information see Linux kernel Documentation/ABI/testing/sysfs-block.
10
 */
11
#include <stdio.h>
12
#include <string.h>
13
#include <stdlib.h>
14
#include <inttypes.h>
15
#include <sys/types.h>
16
#include <sys/stat.h>
17
#include <unistd.h>
18
#include <errno.h>
19
20
#include "sysfs.h"
21
#include "topology.h"
22
23
/*
24
 * Sysfs topology values (since 2.6.31, May 2009).
25
 */
26
static const struct topology_val {
27
28
  /* /sys/dev/block/<maj>:<min>/<ATTR> */
29
  const char * const attr;
30
31
  /* functions to set probing result */
32
  int (*set_ulong)(blkid_probe, unsigned long);
33
  int (*set_int)(blkid_probe, int);
34
  int (*set_u64)(blkid_probe, uint64_t);
35
36
} topology_vals[] = {
37
  { "alignment_offset", NULL, blkid_topology_set_alignment_offset },
38
  { "queue/minimum_io_size", blkid_topology_set_minimum_io_size },
39
  { "queue/optimal_io_size", blkid_topology_set_optimal_io_size },
40
  { "queue/physical_block_size", blkid_topology_set_physical_sector_size },
41
  { "queue/dax", blkid_topology_set_dax },
42
  { "diskseq", .set_u64 = blkid_topology_set_diskseq },
43
};
44
45
static int probe_sysfs_tp(blkid_probe pr,
46
    const struct blkid_idmag *mag __attribute__((__unused__)))
47
0
{
48
0
  dev_t dev;
49
0
  int rc, set_parent = 1;
50
0
  struct path_cxt *pc;
51
0
  size_t i, count = 0;
52
53
0
  dev = blkid_probe_get_devno(pr);
54
0
  if (!dev)
55
0
    return 1;
56
0
  pc = ul_new_sysfs_path(dev, NULL, NULL);
57
0
  if (!pc)
58
0
    return 1;
59
60
0
  rc = 1;   /* nothing (default) */
61
62
0
  for (i = 0; i < ARRAY_SIZE(topology_vals); i++) {
63
0
    const struct topology_val *val = &topology_vals[i];
64
0
    int ok = ul_path_access(pc, F_OK, val->attr) == 0;
65
66
0
    rc = 1; /* nothing */
67
68
0
    if (!ok && set_parent) {
69
0
      dev_t disk = blkid_probe_get_wholedisk_devno(pr);
70
0
      set_parent = 0;
71
72
      /*
73
       * Read attributes from "disk" if the current device is
74
       * a partition. Note that sysfs ul_path_* API is able
75
       * to redirect requests to attributes if parent is set.
76
       */
77
0
      if (disk && disk != dev) {
78
0
        struct path_cxt *parent = ul_new_sysfs_path(disk, NULL, NULL);
79
0
        if (!parent)
80
0
          goto done;
81
82
0
        sysfs_blkdev_set_parent(pc, parent);
83
0
        ul_unref_path(parent);
84
85
        /* try it again */
86
0
        ok = ul_path_access(pc, F_OK, val->attr) == 0;
87
0
      }
88
0
    }
89
0
    if (!ok)
90
0
      continue; /* attribute does not exist */
91
92
0
    if (val->set_ulong) {
93
0
      uint64_t data;
94
95
0
      if (ul_path_read_u64(pc, &data, val->attr) != 0)
96
0
        continue;
97
0
      rc = val->set_ulong(pr, (unsigned long) data);
98
99
0
    } else if (val->set_int) {
100
0
      int64_t data;
101
102
0
      if (ul_path_read_s64(pc, &data, val->attr) != 0)
103
0
        continue;
104
0
      rc = val->set_int(pr, (int) data);
105
0
    } else if (val->set_u64) {
106
0
      uint64_t data;
107
108
0
      if (ul_path_read_u64(pc, &data, val->attr) != 0)
109
0
        continue;
110
0
      rc = val->set_u64(pr, data);
111
0
    }
112
113
0
    if (rc < 0)
114
0
      goto done; /* error */
115
0
    if (rc == 0)
116
0
      count++;
117
0
  }
118
119
0
done:
120
0
  ul_unref_path(pc);    /* unref pc and parent */
121
0
  if (count)
122
0
    return 0;   /* success */
123
0
  return rc;     /* error or nothing */
124
0
}
125
126
const struct blkid_idinfo sysfs_tp_idinfo =
127
{
128
  .name   = "sysfs",
129
  .probefunc  = probe_sysfs_tp,
130
  .magics   = BLKID_NONE_MAGIC
131
};
132