~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/topology/topology.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 */
 
56
static int topology_probe(blkid_probe pr, struct blkid_chain *chn);
 
57
static void topology_free(blkid_probe pr, void *data);
 
58
static int topology_is_complete(blkid_probe pr);
 
59
static int topology_set_logical_sector_size(blkid_probe pr);
 
60
 
 
61
/*
 
62
 * Binary interface
 
63
 */
 
64
struct 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
 */
 
75
static 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
 */
 
91
const 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
 */
 
111
int 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
 */
 
136
blkid_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
 */
 
145
static 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
 
 
208
static void topology_free(blkid_probe pr __attribute__((__unused__)),
 
209
                          void *data)
 
210
{
 
211
        free(data);
 
212
}
 
213
 
 
214
static 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
                unsigned long *v =
 
226
                        (unsigned long *) (chn->data + structoff);
 
227
                *v = data;
 
228
                return 0;
 
229
        }
 
230
        return blkid_probe_sprintf_value(pr, name, "%llu", data);
 
231
}
 
232
 
 
233
/* the topology info is complete when we have at least "minimum_io_size" which
 
234
 * is provided by all blkid topology drivers */
 
235
static int topology_is_complete(blkid_probe pr)
 
236
{
 
237
        struct blkid_chain *chn = blkid_probe_get_chain(pr);
 
238
 
 
239
        if (!chn)
 
240
                return FALSE;
 
241
 
 
242
        if (chn->binary && chn->data) {
 
243
                blkid_topology tp = (blkid_topology) chn->data;
 
244
                if (tp->minimum_io_size)
 
245
                        return TRUE;
 
246
        }
 
247
 
 
248
        return __blkid_probe_lookup_value(pr, "MINIMUM_IO_SIZE") ? TRUE : FALSE;
 
249
}
 
250
 
 
251
int blkid_topology_set_alignment_offset(blkid_probe pr, int val)
 
252
{
 
253
        unsigned long xval;
 
254
 
 
255
        /* Welcome to Hell. The kernel is able to return -1 as an
 
256
         * alignment_offset if no compatible sizes and alignments
 
257
         * exist for stacked devices.
 
258
         *
 
259
         * There is no way how libblkid caller can respond to the value -1, so
 
260
         * we will hide this corner case...
 
261
         *
 
262
         * (TODO: maybe we can export an extra boolean value 'misaligned' rather
 
263
         *  then complete hide this problem.)
 
264
         */
 
265
        xval = val < 0 ? 0 : val;
 
266
 
 
267
        return topology_set_value(pr,
 
268
                        "ALIGNMENT_OFFSET",
 
269
                        offsetof(struct blkid_struct_topology, alignment_offset),
 
270
                        xval);
 
271
}
 
272
 
 
273
int blkid_topology_set_minimum_io_size(blkid_probe pr, unsigned long val)
 
274
{
 
275
        return topology_set_value(pr,
 
276
                        "MINIMUM_IO_SIZE",
 
277
                        offsetof(struct blkid_struct_topology, minimum_io_size),
 
278
                        val);
 
279
}
 
280
 
 
281
int blkid_topology_set_optimal_io_size(blkid_probe pr, unsigned long val)
 
282
{
 
283
        return topology_set_value(pr,
 
284
                        "OPTIMAL_IO_SIZE",
 
285
                        offsetof(struct blkid_struct_topology, optimal_io_size),
 
286
                        val);
 
287
}
 
288
 
 
289
/* BLKSSZGET is provided on all systems since 2.3.3 -- so we don't have to
 
290
 * waste time with sysfs.
 
291
 */
 
292
static int topology_set_logical_sector_size(blkid_probe pr)
 
293
{
 
294
        unsigned long val = blkid_probe_get_sectorsize(pr);
 
295
 
 
296
        if (!val)
 
297
                return -1;
 
298
 
 
299
        return topology_set_value(pr,
 
300
                        "LOGICAL_SECTOR_SIZE",
 
301
                        offsetof(struct blkid_struct_topology, logical_sector_size),
 
302
                        val);
 
303
}
 
304
 
 
305
int blkid_topology_set_physical_sector_size(blkid_probe pr, unsigned long val)
 
306
{
 
307
        return topology_set_value(pr,
 
308
                        "PHYSICAL_SECTOR_SIZE",
 
309
                        offsetof(struct blkid_struct_topology, physical_sector_size),
 
310
                        val);
 
311
}
 
312
 
 
313
/**
 
314
 * blkid_topology_get_alignment_offset:
 
315
 * @tp: topology
 
316
 *
 
317
 * Returns: alignment offset in bytes or 0.
 
318
 */
 
319
unsigned long blkid_topology_get_alignment_offset(blkid_topology tp)
 
320
{
 
321
        return tp ? tp->alignment_offset : 0;
 
322
}
 
323
 
 
324
/**
 
325
 * blkid_topology_get_minimum_io_size:
 
326
 * @tp: topology
 
327
 *
 
328
 * Returns: minimum io size in bytes or 0.
 
329
 */
 
330
unsigned long blkid_topology_get_minimum_io_size(blkid_topology tp)
 
331
{
 
332
        return tp ? tp->minimum_io_size : 0;
 
333
}
 
334
 
 
335
/**
 
336
 * blkid_topology_get_optimal_io_size
 
337
 * @tp: topology
 
338
 *
 
339
 * Returns: optimal io size in bytes or 0.
 
340
 */
 
341
unsigned long blkid_topology_get_optimal_io_size(blkid_topology tp)
 
342
{
 
343
        return tp ? tp->optimal_io_size : 0;
 
344
}
 
345
 
 
346
/**
 
347
 * blkid_topology_get_logical_sector_size
 
348
 * @tp: topology
 
349
 *
 
350
 * Returns: logical sector size (BLKSSZGET ioctl) in bytes or 0.
 
351
 */
 
352
unsigned long blkid_topology_get_logical_sector_size(blkid_topology tp)
 
353
{
 
354
        return tp ? tp->logical_sector_size : 0;
 
355
}
 
356
 
 
357
/**
 
358
 * blkid_topology_get_physical_sector_size
 
359
 * @tp: topology
 
360
 *
 
361
 * Returns: logical sector size (BLKSSZGET ioctl) in bytes or 0.
 
362
 */
 
363
unsigned long blkid_topology_get_physical_sector_size(blkid_topology tp)
 
364
{
 
365
        return tp ? tp->physical_sector_size : 0;
 
366
}
 
367