blob: a04b20a374f9895d403321bb070ee7a6199c4c2e [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
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 */
26static struct topology_val {
27
28 /* /sys/dev/block/<maj>:<min>/<ATTR> */
29 const char *attr;
30
31 /* functions to set probing resut */
32 int (*set_ulong)(blkid_probe, unsigned long);
33 int (*set_int)(blkid_probe, int);
34
35} topology_vals[] = {
36 { "alignment_offset", NULL, blkid_topology_set_alignment_offset },
37 { "queue/minimum_io_size", blkid_topology_set_minimum_io_size },
38 { "queue/optimal_io_size", blkid_topology_set_optimal_io_size },
39 { "queue/physical_block_size", blkid_topology_set_physical_sector_size },
40};
41
42static int probe_sysfs_tp(blkid_probe pr,
43 const struct blkid_idmag *mag __attribute__((__unused__)))
44{
45 dev_t dev, disk = 0;
46 int rc;
47 struct sysfs_cxt sysfs = UL_SYSFSCXT_EMPTY,
48 parent = UL_SYSFSCXT_EMPTY;
49 size_t i, count = 0;
50
51 dev = blkid_probe_get_devno(pr);
52 if (!dev || sysfs_init(&sysfs, dev, NULL) != 0)
53 return 1;
54
55 rc = 1; /* nothing (default) */
56
57 for (i = 0; i < ARRAY_SIZE(topology_vals); i++) {
58 struct topology_val *val = &topology_vals[i];
59 int ok = sysfs_has_attribute(&sysfs, val->attr);
60
61 rc = 1; /* nothing */
62
63 if (!ok) {
64 if (!disk) {
65 /*
66 * Read atrributes from "disk" if the current
67 * device is a partition.
68 */
69 disk = blkid_probe_get_wholedisk_devno(pr);
70 if (disk && disk != dev) {
71 if (sysfs_init(&parent, disk, NULL) != 0)
72 goto done;
73
74 sysfs.parent = &parent;
75 ok = sysfs_has_attribute(&sysfs,
76 val->attr);
77 }
78 }
79 if (!ok)
80 continue; /* attribute does not exist */
81 }
82
83 if (val->set_ulong) {
84 uint64_t data;
85
86 if (sysfs_read_u64(&sysfs, val->attr, &data) != 0)
87 continue;
88 rc = val->set_ulong(pr, (unsigned long) data);
89
90 } else if (val->set_int) {
91 int64_t data;
92
93 if (sysfs_read_s64(&sysfs, val->attr, &data) != 0)
94 continue;
95 rc = val->set_int(pr, (int) data);
96 }
97
98 if (rc < 0)
99 goto done; /* error */
100 if (rc == 0)
101 count++;
102 }
103
104done:
105 sysfs_deinit(&sysfs);
106 sysfs_deinit(&parent);
107
108 if (count)
109 return 0; /* success */
110 return rc; /* error or nothing */
111}
112
113const struct blkid_idinfo sysfs_tp_idinfo =
114{
115 .name = "sysfs",
116 .probefunc = probe_sysfs_tp,
117 .magics = BLKID_NONE_MAGIC
118};
119