2001-10-01 23:29:52 +04:00
/*
* Copyright ( C ) 2001 Sistina Software
*
* lvm is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* lvm is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with GNU CC ; see the file COPYING . If not , write to
* the Free Software Foundation , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*
*/
# include "dbg_malloc.h"
# include "log.h"
# include "dev-cache.h"
# include "filter.h"
2002-01-16 02:34:13 +03:00
# include "lvm-string.h"
2001-10-01 23:29:52 +04:00
2001-10-09 21:20:02 +04:00
# include <stdlib.h>
# include <dirent.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <string.h>
2002-01-24 16:36:33 +03:00
# include <ctype.h>
2001-10-23 16:33:57 +04:00
# include <fcntl.h>
2001-10-09 21:20:02 +04:00
# include <linux/kdev_t.h>
# define NUMBER_OF_MAJORS 256
typedef struct {
char * name ;
int max_partitions ;
} device_info_t ;
2002-01-24 16:36:33 +03:00
static int _md_major = - 1 ;
2001-10-09 21:20:02 +04:00
static device_info_t device_info [ ] = {
{ " ide " , 16 } , /* IDE disk */
{ " sd " , 16 } , /* SCSI disk */
{ " md " , 16 } , /* Multiple Disk driver (SoftRAID) */
{ " loop " , 16 } , /* Loop device */
{ " dasd " , 4 } , /* DASD disk (IBM S/390, zSeries) */
{ " dac960 " , 8 } , /* DAC960 */
{ " nbd " , 16 } , /* Network Block Device */
{ " ida " , 16 } , /* Compaq SMART2 */
{ " cciss " , 16 } , /* Compaq CCISS array */
{ " ubd " , 16 } , /* User-mode virtual block device */
2002-01-16 21:10:08 +03:00
{ " ataraid " , 16 } , /* ATA Raid */
2001-10-09 21:20:02 +04:00
{ NULL , 0 }
} ;
2002-01-16 02:34:13 +03:00
static int * scan_proc_dev ( const char * proc ) ;
2001-10-09 21:20:02 +04:00
2001-10-25 18:04:18 +04:00
static int passes_lvm_type_device_filter ( struct dev_filter * f ,
struct device * dev )
2001-10-01 23:29:52 +04:00
{
2001-10-23 16:33:57 +04:00
int fd ;
2001-10-25 18:04:18 +04:00
const char * name = dev_name ( dev ) ;
2001-10-23 16:33:57 +04:00
2001-10-09 21:20:02 +04:00
/* Is this a recognised device type? */
if ( ! ( ( ( int * ) f - > private ) [ MAJOR ( dev - > dev ) ] ) )
return 0 ;
2001-10-23 16:33:57 +04:00
/* Check it's accessible */
2002-04-24 22:20:51 +04:00
if ( ( fd = open ( name , O_RDONLY ) ) < 0 ) {
log_debug ( " Unable to open %s: %s " , name , strerror ( errno ) ) ;
2001-10-23 16:33:57 +04:00
return 0 ;
}
2002-04-24 22:20:51 +04:00
close ( fd ) ;
2001-10-23 16:33:57 +04:00
return 1 ;
2001-10-01 23:29:52 +04:00
}
2002-01-16 02:34:13 +03:00
struct dev_filter * lvm_type_filter_create ( const char * proc )
2001-10-01 23:29:52 +04:00
{
struct dev_filter * f ;
2002-04-24 22:20:51 +04:00
if ( ! ( f = dbg_malloc ( sizeof ( struct dev_filter ) ) ) ) {
2001-10-23 16:33:57 +04:00
log_error ( " LVM type filter allocation failed " ) ;
2001-10-01 23:29:52 +04:00
return NULL ;
}
2001-10-23 15:50:49 +04:00
f - > passes_filter = passes_lvm_type_device_filter ;
2001-10-23 16:33:57 +04:00
f - > destroy = lvm_type_filter_destroy ;
2001-10-09 21:20:02 +04:00
2002-01-16 02:34:13 +03:00
if ( ! ( f - > private = scan_proc_dev ( proc ) ) )
2001-10-09 21:20:02 +04:00
return NULL ;
2001-10-01 23:29:52 +04:00
return f ;
}
2002-01-24 16:36:33 +03:00
int md_major ( void )
{
return _md_major ;
}
2001-10-23 15:50:49 +04:00
void lvm_type_filter_destroy ( struct dev_filter * f )
2001-10-01 23:29:52 +04:00
{
2001-10-16 20:25:28 +04:00
dbg_free ( f - > private ) ;
2001-10-01 23:29:52 +04:00
dbg_free ( f ) ;
return ;
}
2002-01-16 02:34:13 +03:00
static int * scan_proc_dev ( const char * proc )
2001-10-09 21:20:02 +04:00
{
char line [ 80 ] ;
2002-01-16 02:34:13 +03:00
char proc_devices [ PATH_MAX ] ;
FILE * pd = NULL ;
2001-10-09 21:20:02 +04:00
int ret = 0 ;
int i , j = 0 ;
int line_maj = 0 ;
int blocksection = 0 ;
int dev_len = 0 ;
int * max_partitions_by_major ;
2002-04-24 22:20:51 +04:00
if ( ! ( max_partitions_by_major =
dbg_malloc ( sizeof ( int ) * NUMBER_OF_MAJORS ) ) ) {
2001-10-09 21:20:02 +04:00
log_error ( " Filter failed to allocate max_partitions_by_major " ) ;
return NULL ;
}
2002-04-24 22:20:51 +04:00
if ( lvm_snprintf ( proc_devices , sizeof ( proc_devices ) ,
2002-01-16 02:34:13 +03:00
" %s/devices " , proc ) < 0 ) {
log_error ( " Failed to create /proc/devices string " ) ;
return NULL ;
}
if ( ! ( pd = fopen ( proc_devices , " r " ) ) ) {
log_sys_error ( " fopen " , proc_devices ) ;
2001-10-09 21:20:02 +04:00
return NULL ;
}
2002-04-24 22:20:51 +04:00
memset ( max_partitions_by_major , 0 , sizeof ( int ) * NUMBER_OF_MAJORS ) ;
2002-01-16 02:34:13 +03:00
while ( fgets ( line , 80 , pd ) ! = NULL ) {
2001-10-09 21:20:02 +04:00
i = 0 ;
while ( line [ i ] = = ' ' & & line [ i ] ! = ' \0 ' )
i + + ;
/* If it's not a number it may be name of section */
line_maj = atoi ( ( ( char * ) ( line + i ) ) ) ;
if ( ! line_maj ) {
blocksection = ( line [ i ] = = ' B ' ) ? 1 : 0 ;
continue ;
}
/* We only want block devices ... */
if ( ! blocksection )
continue ;
/* Find the start of the device major name */
while ( line [ i ] ! = ' ' & & line [ i ] ! = ' \0 ' )
i + + ;
while ( line [ i ] = = ' ' & & line [ i ] ! = ' \0 ' )
i + + ;
2002-01-24 16:36:33 +03:00
/* Look for md device */
if ( ! strncmp ( " md " , line + i , 2 ) & & isspace ( * ( line + i + 2 ) ) )
_md_major = line_maj ;
2001-10-09 21:20:02 +04:00
/* Go through the valid device names and if there is a
2002-04-24 22:20:51 +04:00
match store max number of partitions */
2001-10-09 21:20:02 +04:00
for ( j = 0 ; device_info [ j ] . name ! = NULL ; j + + ) {
dev_len = strlen ( device_info [ j ] . name ) ;
if ( dev_len < = strlen ( line + i )
& & ! strncmp ( device_info [ j ] . name , line + i , dev_len )
& & ( line_maj < NUMBER_OF_MAJORS ) ) {
max_partitions_by_major [ line_maj ] =
device_info [ j ] . max_partitions ;
ret + + ;
break ;
}
}
}
2002-01-16 02:34:13 +03:00
fclose ( pd ) ;
2001-10-09 21:20:02 +04:00
return max_partitions_by_major ;
}