LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/filters - filter.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 51 134 38.1 %
Date: 2010-04-13 Functions: 3 9 33.3 %
Branches: 37 106 34.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
       4                 :            :  *
       5                 :            :  * This file is part of LVM2.
       6                 :            :  *
       7                 :            :  * This copyrighted material is made available to anyone wishing to use,
       8                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :            :  * of the GNU Lesser General Public License v.2.1.
      10                 :            :  *
      11                 :            :  * You should have received a copy of the GNU Lesser General Public License
      12                 :            :  * along with this program; if not, write to the Free Software Foundation,
      13                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "lib.h"
      17                 :            : #include "dev-cache.h"
      18                 :            : #include "filter.h"
      19                 :            : #include "lvm-string.h"
      20                 :            : #include "config.h"
      21                 :            : #include "metadata.h"
      22                 :            : #include "activate.h"
      23                 :            : 
      24                 :            : #include <dirent.h>
      25                 :            : #include <unistd.h>
      26                 :            : #include <ctype.h>
      27                 :            : #include <fcntl.h>
      28                 :            : #include <limits.h>
      29                 :            : 
      30                 :            : #define NUMBER_OF_MAJORS 4096
      31                 :            : 
      32                 :            : /* 0 means LVM won't use this major number. */
      33                 :            : static int _max_partitions_by_major[NUMBER_OF_MAJORS];
      34                 :            : 
      35                 :            : typedef struct {
      36                 :            :         const char *name;
      37                 :            :         const int max_partitions;
      38                 :            : } device_info_t;
      39                 :            : 
      40                 :            : static int _md_major = -1;
      41                 :            : static int _blkext_major = -1;
      42                 :            : static int _drbd_major = -1;
      43                 :            : static int _device_mapper_major = -1;
      44                 :            : 
      45                 :          0 : int md_major(void)
      46                 :            : {
      47                 :          0 :         return _md_major;
      48                 :            : }
      49                 :            : 
      50                 :          0 : int blkext_major(void)
      51                 :            : {
      52                 :          0 :         return _blkext_major;
      53                 :            : }
      54                 :            : 
      55                 :          0 : int dev_subsystem_part_major(const struct device *dev)
      56                 :            : {
      57         [ #  # ]:          0 :         if (MAJOR(dev->dev) == -1)
      58                 :          0 :                 return 0;
      59                 :            : 
      60         [ #  # ]:          0 :         if (MAJOR(dev->dev) == _md_major)
      61                 :          0 :                 return 1;
      62                 :            : 
      63         [ #  # ]:          0 :         if (MAJOR(dev->dev) == _drbd_major)
      64                 :          0 :                 return 1;
      65                 :            : 
      66                 :          0 :         return 0;
      67                 :            : }
      68                 :            : 
      69                 :          0 : const char *dev_subsystem_name(const struct device *dev)
      70                 :            : {
      71         [ #  # ]:          0 :         if (MAJOR(dev->dev) == _md_major)
      72                 :          0 :                 return "MD";
      73                 :            : 
      74         [ #  # ]:          0 :         if (MAJOR(dev->dev) == _drbd_major)
      75                 :          0 :                 return "DRBD";
      76                 :            : 
      77                 :          0 :         return "";
      78                 :            : }
      79                 :            : 
      80                 :            : /*
      81                 :            :  * Devices are only checked for partition tables if their minor number
      82                 :            :  * is a multiple of the number corresponding to their type below
      83                 :            :  * i.e. this gives the granularity of whole-device minor numbers.
      84                 :            :  * Use 1 if the device is not partitionable.
      85                 :            :  *
      86                 :            :  * The list can be supplemented with devices/types in the config file.
      87                 :            :  */
      88                 :            : static const device_info_t device_info[] = {
      89                 :            :         {"ide", 64},          /* IDE disk */
      90                 :            :         {"sd", 16},           /* SCSI disk */
      91                 :            :         {"md", 1},            /* Multiple Disk driver (SoftRAID) */
      92                 :            :         {"mdp", 1},           /* Partitionable MD */
      93                 :            :         {"loop", 1},          /* Loop device */
      94                 :            :         {"dasd", 4},          /* DASD disk (IBM S/390, zSeries) */
      95                 :            :         {"dac960", 8},                /* DAC960 */
      96                 :            :         {"nbd", 16},          /* Network Block Device */
      97                 :            :         {"ida", 16},          /* Compaq SMART2 */
      98                 :            :         {"cciss", 16},                /* Compaq CCISS array */
      99                 :            :         {"ubd", 16},          /* User-mode virtual block device */
     100                 :            :         {"ataraid", 16},      /* ATA Raid */
     101                 :            :         {"drbd", 16},         /* Distributed Replicated Block Device */
     102                 :            :         {"emcpower", 16},     /* EMC Powerpath */
     103                 :            :         {"power2", 16},               /* EMC Powerpath */
     104                 :            :         {"i2o_block", 16},    /* i2o Block Disk */
     105                 :            :         {"iseries/vd", 8},    /* iSeries disks */
     106                 :            :         {"gnbd", 1},          /* Network block device */
     107                 :            :         {"ramdisk", 1},               /* RAM disk */
     108                 :            :         {"aoe", 16},          /* ATA over Ethernet */
     109                 :            :         {"device-mapper", 1}, /* Other mapped devices */
     110                 :            :         {"xvd", 16},          /* Xen virtual block device */
     111                 :            :         {"vdisk", 8},         /* SUN's LDOM virtual block device */
     112                 :            :         {"ps3disk", 16},      /* PlayStation 3 internal disk */
     113                 :            :         {"virtblk", 8},               /* VirtIO disk */
     114                 :            :         {"mmc", 16},          /* MMC block device */
     115                 :            :         {"blkext", 1},                /* Extended device partitions */
     116                 :            :         {NULL, 0}
     117                 :            : };
     118                 :            : 
     119                 :          0 : static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)),
     120                 :            :                                           struct device *dev)
     121                 :            : {
     122                 :          0 :         const char *name = dev_name(dev);
     123                 :          0 :         int ret = 0;
     124                 :            :         uint64_t size;
     125                 :            : 
     126                 :            :         /* Is this a recognised device type? */
     127         [ #  # ]:          0 :         if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
     128                 :          0 :                 log_debug("%s: Skipping: Unrecognised LVM device type %"
     129                 :            :                           PRIu64, name, (uint64_t) MAJOR(dev->dev));
     130                 :          0 :                 return 0;
     131                 :            :         }
     132                 :            : 
     133                 :            :         /* Skip suspended devices */
     134 [ #  #  #  #  # :          0 :         if (MAJOR(dev->dev) == _device_mapper_major &&
                      # ]
     135                 :          0 :             ignore_suspended_devices() && !device_is_usable(dev->dev)) {
     136                 :          0 :                 log_debug("%s: Skipping: Suspended dm device", name);
     137                 :          0 :                 return 0;
     138                 :            :         }
     139                 :            : 
     140                 :            :         /* Check it's accessible */
     141         [ #  # ]:          0 :         if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
     142                 :          0 :                 log_debug("%s: Skipping: open failed", name);
     143                 :          0 :                 return 0;
     144                 :            :         }
     145                 :            :         
     146                 :            :         /* Check it's not too small */
     147         [ #  # ]:          0 :         if (!dev_get_size(dev, &size)) {
     148                 :          0 :                 log_debug("%s: Skipping: dev_get_size failed", name);
     149                 :          0 :                 goto out;
     150                 :            :         }
     151                 :            : 
     152         [ #  # ]:          0 :         if (size < PV_MIN_SIZE) {
     153                 :          0 :                 log_debug("%s: Skipping: Too small to hold a PV", name);
     154                 :          0 :                 goto out;
     155                 :            :         }
     156                 :            : 
     157         [ #  # ]:          0 :         if (is_partitioned_dev(dev)) {
     158                 :          0 :                 log_debug("%s: Skipping: Partition table signature found",
     159                 :            :                           name);
     160                 :          0 :                 goto out;
     161                 :            :         }
     162                 :            : 
     163                 :          0 :         ret = 1;
     164                 :            : 
     165                 :            :       out:
     166                 :          0 :         dev_close(dev);
     167                 :            : 
     168                 :          0 :         return ret;
     169                 :            : }
     170                 :            : 
     171                 :          3 : static int _scan_proc_dev(const char *proc, const struct config_node *cn)
     172                 :            : {
     173                 :            :         char line[80];
     174                 :            :         char proc_devices[PATH_MAX];
     175                 :          3 :         FILE *pd = NULL;
     176                 :          3 :         int i, j = 0;
     177                 :          3 :         int line_maj = 0;
     178                 :          3 :         int blocksection = 0;
     179                 :          3 :         size_t dev_len = 0;
     180                 :            :         struct config_value *cv;
     181                 :            :         char *name;
     182                 :            : 
     183                 :            : 
     184         [ -  + ]:          3 :         if (!*proc) {
     185                 :          0 :                 log_verbose("No proc filesystem found: using all block device "
     186                 :            :                             "types");
     187         [ #  # ]:          0 :                 for (i = 0; i < NUMBER_OF_MAJORS; i++)
     188                 :          0 :                         _max_partitions_by_major[i] = 1;
     189                 :          0 :                 return 1;
     190                 :            :         }
     191                 :            : 
     192                 :            :         /* All types unrecognised initially */
     193                 :          3 :         memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
     194                 :            : 
     195         [ -  + ]:          3 :         if (dm_snprintf(proc_devices, sizeof(proc_devices),
     196                 :            :                          "%s/devices", proc) < 0) {
     197                 :          0 :                 log_error("Failed to create /proc/devices string");
     198                 :          0 :                 return 0;
     199                 :            :         }
     200                 :            : 
     201         [ -  + ]:          3 :         if (!(pd = fopen(proc_devices, "r"))) {
     202                 :          0 :                 log_sys_error("fopen", proc_devices);
     203                 :          0 :                 return 0;
     204                 :            :         }
     205                 :            : 
     206         [ +  + ]:        126 :         while (fgets(line, 80, pd) != NULL) {
     207                 :        123 :                 i = 0;
     208 [ +  + ][ +  - ]:        228 :                 while (line[i] == ' ' && line[i] != '\0')
     209                 :        105 :                         i++;
     210                 :            : 
     211                 :            :                 /* If it's not a number it may be name of section */
     212                 :        123 :                 line_maj = atoi(((char *) (line + i)));
     213         [ +  + ]:        123 :                 if (!line_maj) {
     214                 :          9 :                         blocksection = (line[i] == 'B') ? 1 : 0;
     215                 :          9 :                         continue;
     216                 :            :                 }
     217                 :            : 
     218                 :            :                 /* We only want block devices ... */
     219         [ +  + ]:        114 :                 if (!blocksection)
     220                 :         51 :                         continue;
     221                 :            : 
     222                 :            :                 /* Find the start of the device major name */
     223 [ +  + ][ +  - ]:        207 :                 while (line[i] != ' ' && line[i] != '\0')
     224                 :        144 :                         i++;
     225 [ +  + ][ +  - ]:        126 :                 while (line[i] == ' ' && line[i] != '\0')
     226                 :         63 :                         i++;
     227                 :            : 
     228                 :            :                 /* Look for md device */
     229 [ -  + ][ #  # ]:         63 :                 if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
     230                 :          0 :                         _md_major = line_maj;
     231                 :            : 
     232                 :            :                 /* Look for blkext device */
     233 [ +  + ][ +  - ]:         63 :                 if (!strncmp("blkext", line + i, 6) && isspace(*(line + i + 6)))
     234                 :          3 :                         _blkext_major = line_maj;
     235                 :            : 
     236                 :            :                 /* Look for drbd device */
     237 [ -  + ][ #  # ]:         63 :                 if (!strncmp("drbd", line + i, 4) && isspace(*(line + i + 4)))
     238                 :          0 :                         _drbd_major = line_maj;
     239                 :            : 
     240                 :            :                 /* Look for device-mapper device */
     241                 :            :                 /* FIXME Cope with multiple majors */
     242 [ +  + ][ +  - ]:         63 :                 if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
     243                 :          3 :                         _device_mapper_major = line_maj;
     244                 :            : 
     245                 :            :                 /* Go through the valid device names and if there is a
     246                 :            :                    match store max number of partitions */
     247         [ +  + ]:        396 :                 for (j = 0; device_info[j].name != NULL; j++) {
     248                 :        393 :                         dev_len = strlen(device_info[j].name);
     249 [ +  + ][ +  + ]:        393 :                         if (dev_len <= strlen(line + i) &&
                 [ +  - ]
     250                 :        324 :                             !strncmp(device_info[j].name, line + i, dev_len) &&
     251                 :            :                             (line_maj < NUMBER_OF_MAJORS)) {
     252                 :        120 :                                 _max_partitions_by_major[line_maj] =
     253                 :         60 :                                     device_info[j].max_partitions;
     254                 :         60 :                                 break;
     255                 :            :                         }
     256                 :            :                 }
     257                 :            : 
     258         [ +  - ]:         63 :                 if (!cn)
     259                 :         63 :                         continue;
     260                 :            : 
     261                 :            :                 /* Check devices/types for local variations */
     262         [ #  # ]:          0 :                 for (cv = cn->v; cv; cv = cv->next) {
     263         [ #  # ]:          0 :                         if (cv->type != CFG_STRING) {
     264                 :          0 :                                 log_error("Expecting string in devices/types "
     265                 :            :                                           "in config file");
     266         [ #  # ]:          0 :                                 if (fclose(pd))
     267                 :          0 :                                         log_sys_error("fclose", proc_devices);
     268                 :          0 :                                 return 0;
     269                 :            :                         }
     270                 :          0 :                         dev_len = strlen(cv->v.str);
     271                 :          0 :                         name = cv->v.str;
     272                 :          0 :                         cv = cv->next;
     273 [ #  # ][ #  # ]:          0 :                         if (!cv || cv->type != CFG_INT) {
     274                 :          0 :                                 log_error("Max partition count missing for %s "
     275                 :            :                                           "in devices/types in config file",
     276                 :            :                                           name);
     277         [ #  # ]:          0 :                                 if (fclose(pd))
     278                 :          0 :                                         log_sys_error("fclose", proc_devices);
     279                 :          0 :                                 return 0;
     280                 :            :                         }
     281         [ #  # ]:          0 :                         if (!cv->v.i) {
     282                 :          0 :                                 log_error("Zero partition count invalid for "
     283                 :            :                                           "%s in devices/types in config file",
     284                 :            :                                           name);
     285         [ #  # ]:          0 :                                 if (fclose(pd))
     286                 :          0 :                                         log_sys_error("fclose", proc_devices);
     287                 :          0 :                                 return 0;
     288                 :            :                         }
     289 [ #  # ][ #  # ]:          0 :                         if (dev_len <= strlen(line + i) &&
                 [ #  # ]
     290                 :          0 :                             !strncmp(name, line + i, dev_len) &&
     291                 :            :                             (line_maj < NUMBER_OF_MAJORS)) {
     292                 :          0 :                                 _max_partitions_by_major[line_maj] = cv->v.i;
     293                 :          0 :                                 break;
     294                 :            :                         }
     295                 :            :                 }
     296                 :            :         }
     297                 :            : 
     298         [ -  + ]:          3 :         if (fclose(pd))
     299                 :          0 :                 log_sys_error("fclose", proc_devices);
     300                 :            : 
     301                 :          3 :         return 1;
     302                 :            : }
     303                 :            : 
     304                 :          0 : int max_partitions(int major)
     305                 :            : {
     306                 :          0 :         return _max_partitions_by_major[major];
     307                 :            : }
     308                 :            : 
     309                 :          3 : struct dev_filter *lvm_type_filter_create(const char *proc,
     310                 :            :                                           const struct config_node *cn)
     311                 :            : {
     312                 :            :         struct dev_filter *f;
     313                 :            : 
     314         [ -  + ]:          3 :         if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
     315                 :          0 :                 log_error("LVM type filter allocation failed");
     316                 :          0 :                 return NULL;
     317                 :            :         }
     318                 :            : 
     319                 :          3 :         f->passes_filter = _passes_lvm_type_device_filter;
     320                 :          3 :         f->destroy = lvm_type_filter_destroy;
     321                 :          3 :         f->private = NULL;
     322                 :            : 
     323         [ -  + ]:          3 :         if (!_scan_proc_dev(proc, cn)) {
     324                 :          0 :                 dm_free(f);
     325                 :          0 :                 return_NULL;
     326                 :            :         }
     327                 :            : 
     328                 :          3 :         return f;
     329                 :            : }
     330                 :            : 
     331                 :          3 : void lvm_type_filter_destroy(struct dev_filter *f)
     332                 :            : {
     333                 :          3 :         dm_free(f);
     334                 :          3 : }

Generated by: LCOV version 1.8