blob: 9d4e7bdf18d4eee65e5aefa4a429cca0a82b1683 [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
2 * topology - gathers information about device topology
3 *
4 * Copyright 2009 Red Hat, Inc. All rights reserved.
5 *
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
8 */
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <stddef.h>
14
15#include "topology.h"
16
17/**
18 * SECTION:topology
19 * @title: Topology information
20 * @short_description: block device topology information.
21 *
22 * The topology chain provides details about Linux block devices, for more
23 * information see:
24 *
25 * Linux kernel Documentation/ABI/testing/sysfs-block
26 *
27 * NAME=value (tags) interface is enabled by blkid_probe_enable_topology(),
28 * and provides:
29 *
30 * @LOGICAL_SECTOR_SIZE: this is the smallest unit the storage device can
31 * address. It is typically 512 bytes.
32 *
33 * @PHYSICAL_SECTOR_SIZE: this is the smallest unit a physical storage device
34 * can write atomically. It is usually the same as the
35 * logical sector size but may be bigger.
36 *
37 * @MINIMUM_IO_SIZE: minimum size which is the device's preferred unit of I/O.
38 * For RAID arrays it is often the stripe chunk size.
39 *
40 * @OPTIMAL_IO_SIZE: usually the stripe width for RAID or zero. For RAID arrays
41 * it is usually the stripe width or the internal track size.
42 *
43 * @ALIGNMENT_OFFSET: indicates how many bytes the beginning of the device is
44 * offset from the disk's natural alignment.
45 *
46 * The NAME=value tags are not defined when the corresponding topology value
47 * is zero. The MINIMUM_IO_SIZE should be always defined if kernel provides
48 * topology information.
49 *
50 * Binary interface:
51 *
52 * blkid_probe_get_topology()
53 *
54 * blkid_topology_get_'VALUENAME'()
55 */
56static int topology_probe(blkid_probe pr, struct blkid_chain *chn);
57static void topology_free(blkid_probe pr, void *data);
58static int topology_is_complete(blkid_probe pr);
59static int topology_set_logical_sector_size(blkid_probe pr);
60
61/*
62 * Binary interface
63 */
64struct blkid_struct_topology {
65 unsigned long alignment_offset;
66 unsigned long minimum_io_size;
67 unsigned long optimal_io_size;
68 unsigned long logical_sector_size;
69 unsigned long physical_sector_size;
70};
71
72/*
73 * Topology chain probing functions
74 */
75static const struct blkid_idinfo *idinfos[] =
76{
77#ifdef __linux__
78 &ioctl_tp_idinfo,
79 &sysfs_tp_idinfo,
80 &md_tp_idinfo,
81 &dm_tp_idinfo,
82 &lvm_tp_idinfo,
83 &evms_tp_idinfo
84#endif
85};
86
87
88/*
89 * Driver definition
90 */
91const struct blkid_chaindrv topology_drv = {
92 .id = BLKID_CHAIN_TOPLGY,
93 .name = "topology",
94 .dflt_enabled = FALSE,
95 .idinfos = idinfos,
96 .nidinfos = ARRAY_SIZE(idinfos),
97 .probe = topology_probe,
98 .safeprobe = topology_probe,
99 .free_data = topology_free
100};
101
102/**
103 * blkid_probe_enable_topology:
104 * @pr: probe
105 * @enable: TRUE/FALSE
106 *
107 * Enables/disables the topology probing for non-binary interface.
108 *
109 * Returns: 0 on success, or -1 in case of error.
110 */
111int blkid_probe_enable_topology(blkid_probe pr, int enable)
112{
113 if (!pr)
114 return -1;
115 pr->chains[BLKID_CHAIN_TOPLGY].enabled = enable;
116 return 0;
117}
118
119/**
120 * blkid_probe_get_topology:
121 * @pr: probe
122 *
123 * This is a binary interface for topology values. See also blkid_topology_*
124 * functions.
125 *
126 * This function is independent on blkid_do_[safe,full]probe() and
127 * blkid_probe_enable_topology() calls.
128 *
129 * WARNING: the returned object will be overwritten by the next
130 * blkid_probe_get_topology() call for the same @pr. If you want to
131 * use more blkid_topopogy objects in the same time you have to create
132 * more blkid_probe handlers (see blkid_new_probe()).
133 *
134 * Returns: blkid_topopogy, or NULL in case of error.
135 */
136blkid_topology blkid_probe_get_topology(blkid_probe pr)
137{
138 return (blkid_topology) blkid_probe_get_binary_data(pr,
139 &pr->chains[BLKID_CHAIN_TOPLGY]);
140}
141
142/*
143 * The blkid_do_probe() backend.
144 */
145static int topology_probe(blkid_probe pr, struct blkid_chain *chn)
146{
147 size_t i;
148
149 if (!pr || chn->idx < -1)
150 return -1;
151
152 if (!S_ISBLK(pr->mode))
153 return -1; /* nothing, works with block devices only */
154
155 if (chn->binary) {
156 DBG(DEBUG_LOWPROBE, printf("initialize topology binary data\n"));
157
158 if (chn->data)
159 /* reset binary data */
160 memset(chn->data, 0,
161 sizeof(struct blkid_struct_topology));
162 else {
163 chn->data = calloc(1,
164 sizeof(struct blkid_struct_topology));
165 if (!chn->data)
166 return -1;
167 }
168 }
169
170 blkid_probe_chain_reset_vals(pr, chn);
171
172 DBG(DEBUG_LOWPROBE,
173 printf("--> starting probing loop [TOPOLOGY idx=%d]\n",
174 chn->idx));
175
176 i = chn->idx < 0 ? 0 : chn->idx + 1U;
177
178 for ( ; i < ARRAY_SIZE(idinfos); i++) {
179 const struct blkid_idinfo *id = idinfos[i];
180
181 chn->idx = i;
182
183 if (id->probefunc) {
184 DBG(DEBUG_LOWPROBE, printf(
185 "%s: call probefunc()\n", id->name));
186 if (id->probefunc(pr, NULL) != 0)
187 continue;
188 }
189
190 if (!topology_is_complete(pr))
191 continue;
192
193 /* generic for all probing drivers */
194 topology_set_logical_sector_size(pr);
195
196 DBG(DEBUG_LOWPROBE,
197 printf("<-- leaving probing loop (type=%s) [TOPOLOGY idx=%d]\n",
198 id->name, chn->idx));
199 return 0;
200 }
201
202 DBG(DEBUG_LOWPROBE,
203 printf("<-- leaving probing loop (failed) [TOPOLOGY idx=%d]\n",
204 chn->idx));
205 return 1;
206}
207
208static void topology_free(blkid_probe pr __attribute__((__unused__)),
209 void *data)
210{
211 free(data);
212}
213
214static int topology_set_value(blkid_probe pr, const char *name,
215 size_t structoff, unsigned long data)
216{
217 struct blkid_chain *chn = blkid_probe_get_chain(pr);
218
219 if (!chn)
220 return -1;
221 if (!data)
222 return 0; /* ignore zeros */
223
224 if (chn->binary) {
225 memcpy(chn->data + structoff, &data, sizeof(data));
226 return 0;
227 }
228 return blkid_probe_sprintf_value(pr, name, "%lu", data);
229}
230
231
232/* the topology info is complete when we have at least "minimum_io_size" which
233 * is provided by all blkid topology drivers */
234static int topology_is_complete(blkid_probe pr)
235{
236 struct blkid_chain *chn = blkid_probe_get_chain(pr);
237
238 if (!chn)
239 return FALSE;
240
241 if (chn->binary && chn->data) {
242 blkid_topology tp = (blkid_topology) chn->data;
243 if (tp->minimum_io_size)
244 return TRUE;
245 }
246
247 return __blkid_probe_lookup_value(pr, "MINIMUM_IO_SIZE") ? TRUE : FALSE;
248}
249
250int blkid_topology_set_alignment_offset(blkid_probe pr, int val)
251{
252 unsigned long xval;
253
254 /* Welcome to Hell. The kernel is able to return -1 as an
255 * alignment_offset if no compatible sizes and alignments
256 * exist for stacked devices.
257 *
258 * There is no way how libblkid caller can respond to the value -1, so
259 * we will hide this corner case...
260 *
261 * (TODO: maybe we can export an extra boolean value 'misaligned' rather
262 * then complete hide this problem.)
263 */
264 xval = val < 0 ? 0 : val;
265
266 return topology_set_value(pr,
267 "ALIGNMENT_OFFSET",
268 offsetof(struct blkid_struct_topology, alignment_offset),
269 xval);
270}
271
272int blkid_topology_set_minimum_io_size(blkid_probe pr, unsigned long val)
273{
274 return topology_set_value(pr,
275 "MINIMUM_IO_SIZE",
276 offsetof(struct blkid_struct_topology, minimum_io_size),
277 val);
278}
279
280int blkid_topology_set_optimal_io_size(blkid_probe pr, unsigned long val)
281{
282 return topology_set_value(pr,
283 "OPTIMAL_IO_SIZE",
284 offsetof(struct blkid_struct_topology, optimal_io_size),
285 val);
286}
287
288/* BLKSSZGET is provided on all systems since 2.3.3 -- so we don't have to
289 * waste time with sysfs.
290 */
291static int topology_set_logical_sector_size(blkid_probe pr)
292{
293 unsigned long val = blkid_probe_get_sectorsize(pr);
294
295 if (!val)
296 return -1;
297
298 return topology_set_value(pr,
299 "LOGICAL_SECTOR_SIZE",
300 offsetof(struct blkid_struct_topology, logical_sector_size),
301 val);
302}
303
304int blkid_topology_set_physical_sector_size(blkid_probe pr, unsigned long val)
305{
306 return topology_set_value(pr,
307 "PHYSICAL_SECTOR_SIZE",
308 offsetof(struct blkid_struct_topology, physical_sector_size),
309 val);
310}
311
312/**
313 * blkid_topology_get_alignment_offset:
314 * @tp: topology
315 *
316 * Returns: alignment offset in bytes or 0.
317 */
318unsigned long blkid_topology_get_alignment_offset(blkid_topology tp)
319{
320 return tp->alignment_offset;
321}
322
323/**
324 * blkid_topology_get_minimum_io_size:
325 * @tp: topology
326 *
327 * Returns: minimum io size in bytes or 0.
328 */
329unsigned long blkid_topology_get_minimum_io_size(blkid_topology tp)
330{
331 return tp->minimum_io_size;
332}
333
334/**
335 * blkid_topology_get_optimal_io_size
336 * @tp: topology
337 *
338 * Returns: optimal io size in bytes or 0.
339 */
340unsigned long blkid_topology_get_optimal_io_size(blkid_topology tp)
341{
342 return tp->optimal_io_size;
343}
344
345/**
346 * blkid_topology_get_logical_sector_size
347 * @tp: topology
348 *
349 * Returns: logical sector size (BLKSSZGET ioctl) in bytes or 0.
350 */
351unsigned long blkid_topology_get_logical_sector_size(blkid_topology tp)
352{
353 return tp->logical_sector_size;
354}
355
356/**
357 * blkid_topology_get_physical_sector_size
358 * @tp: topology
359 *
360 * Returns: logical sector size (BLKSSZGET ioctl) in bytes or 0.
361 */
362unsigned long blkid_topology_get_physical_sector_size(blkid_topology tp)
363{
364 return tp->physical_sector_size;
365}
366