1 /* $NetBSD: filter.c,v 1.1.1.2 2009/12/02 00:26:47 haad Exp $ */
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "dev-cache.h"
21 #include "lvm-string.h"
32 #define NUMBER_OF_MAJORS 4096
34 /* 0 means LVM won't use this major number. */
35 static int _max_partitions_by_major[NUMBER_OF_MAJORS];
39 const int max_partitions;
42 static int _md_major = -1;
43 static int _blkext_major = -1;
44 static int _drbd_major = -1;
45 static int _device_mapper_major = -1;
52 int blkext_major(void)
57 int dev_subsystem_part_major(const struct device *dev)
59 if (MAJOR(dev->dev) == -1)
62 if (MAJOR(dev->dev) == _md_major)
65 if (MAJOR(dev->dev) == _drbd_major)
71 const char *dev_subsystem_name(const struct device *dev)
73 if (MAJOR(dev->dev) == _md_major)
76 if (MAJOR(dev->dev) == _drbd_major)
83 * Devices are only checked for partition tables if their minor number
84 * is a multiple of the number corresponding to their type below
85 * i.e. this gives the granularity of whole-device minor numbers.
86 * Use 1 if the device is not partitionable.
88 * The list can be supplemented with devices/types in the config file.
90 static const device_info_t device_info[] = {
91 {"ide", 64}, /* IDE disk */
92 {"sd", 16}, /* SCSI disk */
93 {"md", 1}, /* Multiple Disk driver (SoftRAID) */
94 {"mdp", 1}, /* Partitionable MD */
95 {"loop", 1}, /* Loop device */
96 {"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
97 {"dac960", 8}, /* DAC960 */
98 {"nbd", 16}, /* Network Block Device */
99 {"ida", 16}, /* Compaq SMART2 */
100 {"cciss", 16}, /* Compaq CCISS array */
101 {"ubd", 16}, /* User-mode virtual block device */
102 {"ataraid", 16}, /* ATA Raid */
103 {"drbd", 16}, /* Distributed Replicated Block Device */
104 {"emcpower", 16}, /* EMC Powerpath */
105 {"power2", 16}, /* EMC Powerpath */
106 {"i2o_block", 16}, /* i2o Block Disk */
107 {"iseries/vd", 8}, /* iSeries disks */
108 {"gnbd", 1}, /* Network block device */
109 {"ramdisk", 1}, /* RAM disk */
110 {"aoe", 16}, /* ATA over Ethernet */
111 {"device-mapper", 1}, /* Other mapped devices */
112 {"xvd", 16}, /* Xen virtual block device */
113 {"vdisk", 8}, /* SUN's LDOM virtual block device */
114 {"ps3disk", 16}, /* PlayStation 3 internal disk */
115 {"virtblk", 8}, /* VirtIO disk */
116 {"mmc", 16}, /* MMC block device */
117 {"blkext", 1}, /* Extended device partitions */
121 static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)),
124 const char *name = dev_name(dev);
128 /* Is this a recognised device type? */
129 if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
130 log_debug("%s: Skipping: Unrecognised LVM device type %"
131 PRIu64, name, (uint64_t) MAJOR(dev->dev));
135 /* Skip suspended devices */
136 if (MAJOR(dev->dev) == _device_mapper_major &&
137 ignore_suspended_devices() && !device_is_usable(dev->dev)) {
138 log_debug("%s: Skipping: Suspended dm device", name);
142 /* Check it's accessible */
143 if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
144 log_debug("%s: Skipping: open failed", name);
148 /* Check it's not too small */
149 if (!dev_get_size(dev, &size)) {
150 log_debug("%s: Skipping: dev_get_size failed", name);
154 if (size < PV_MIN_SIZE) {
155 log_debug("%s: Skipping: Too small to hold a PV", name);
159 if (is_partitioned_dev(dev)) {
160 log_debug("%s: Skipping: Partition table signature found",
173 static int _scan_proc_dev(const char *proc, const struct config_node *cn)
176 char proc_devices[PATH_MAX];
180 int blocksection = 0;
182 struct config_value *cv;
187 log_verbose("No proc filesystem found: using all block device "
189 for (i = 0; i < NUMBER_OF_MAJORS; i++)
190 _max_partitions_by_major[i] = 1;
194 /* All types unrecognised initially */
195 memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
197 if (dm_snprintf(proc_devices, sizeof(proc_devices),
198 "%s/devices", proc) < 0) {
199 log_error("Failed to create /proc/devices string");
203 if (!(pd = fopen(proc_devices, "r"))) {
204 log_sys_error("fopen", proc_devices);
208 while (fgets(line, 80, pd) != NULL) {
210 while (line[i] == ' ' && line[i] != '\0')
213 /* If it's not a number it may be name of section */
214 line_maj = atoi(((char *) (line + i)));
216 blocksection = (line[i] == 'B') ? 1 : 0;
220 /* We only want block devices ... */
224 /* Find the start of the device major name */
225 while (line[i] != ' ' && line[i] != '\0')
227 while (line[i] == ' ' && line[i] != '\0')
230 /* Look for md device */
231 if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
232 _md_major = line_maj;
234 /* Look for blkext device */
235 if (!strncmp("blkext", line + i, 6) && isspace(*(line + i + 6)))
236 _blkext_major = line_maj;
238 /* Look for drbd device */
239 if (!strncmp("drbd", line + i, 4) && isspace(*(line + i + 4)))
240 _drbd_major = line_maj;
242 /* Look for device-mapper device */
243 /* FIXME Cope with multiple majors */
244 if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
245 _device_mapper_major = line_maj;
247 /* Go through the valid device names and if there is a
248 match store max number of partitions */
249 for (j = 0; device_info[j].name != NULL; j++) {
250 dev_len = strlen(device_info[j].name);
251 if (dev_len <= strlen(line + i) &&
252 !strncmp(device_info[j].name, line + i, dev_len) &&
253 (line_maj < NUMBER_OF_MAJORS)) {
254 _max_partitions_by_major[line_maj] =
255 device_info[j].max_partitions;
263 /* Check devices/types for local variations */
264 for (cv = cn->v; cv; cv = cv->next) {
265 if (cv->type != CFG_STRING) {
266 log_error("Expecting string in devices/types "
269 log_sys_error("fclose", proc_devices);
272 dev_len = strlen(cv->v.str);
275 if (!cv || cv->type != CFG_INT) {
276 log_error("Max partition count missing for %s "
277 "in devices/types in config file",
280 log_sys_error("fclose", proc_devices);
284 log_error("Zero partition count invalid for "
285 "%s in devices/types in config file",
288 log_sys_error("fclose", proc_devices);
291 if (dev_len <= strlen(line + i) &&
292 !strncmp(name, line + i, dev_len) &&
293 (line_maj < NUMBER_OF_MAJORS)) {
294 _max_partitions_by_major[line_maj] = cv->v.i;
301 log_sys_error("fclose", proc_devices);
306 int max_partitions(int major)
308 return _max_partitions_by_major[major];
311 struct dev_filter *lvm_type_filter_create(const char *proc,
312 const struct config_node *cn)
314 struct dev_filter *f;
316 if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
317 log_error("LVM type filter allocation failed");
321 f->passes_filter = _passes_lvm_type_device_filter;
322 f->destroy = lvm_type_filter_destroy;
325 if (!_scan_proc_dev(proc, cn)) {
333 void lvm_type_filter_destroy(struct dev_filter *f)