blob: 82b1cf1edfb334443768e579017fdd3f9607086a [file] [log] [blame]
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program 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.
*
* This program is distributed in the hope that it would 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 this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "drivers.h"
#include "md.h"
int
mnt_is_md_subvol(
dev_t dev,
enum md_type *type)
{
*type = MD_TYPE_MD;
if (major(dev) == MD_MAJOR)
return 1;
if (get_driver_block_major("md", major(dev)))
return 1;
*type = MD_TYPE_MDP;
if (get_driver_block_major("mdp", major(dev)))
return 1;
return 0;
}
int
md_get_subvol_stripe(
char *dfile,
sv_type_t type,
int *sunit,
int *swidth,
int *sectalign,
struct stat64 *sb)
{
char *pc;
char *dfile2 = NULL;
enum md_type md_type;
if (mnt_is_md_subvol(sb->st_rdev, &md_type)) {
struct md_array_info md;
int fd;
if (md_type == MD_TYPE_MDP) {
pc = strrchr(dfile, 'd');
if (pc)
pc = strchr(pc, 'p');
if (!pc) {
fprintf(stderr,
_("Error getting MD array device from %s\n"),
dfile);
exit(1);
}
dfile2 = malloc(pc - dfile + 1);
if (dfile2 == NULL) {
fprintf(stderr,
_("Couldn't malloc device string\n"));
exit(1);
}
strncpy(dfile2, dfile, pc - dfile);
dfile2[pc - dfile + 1] = '\0';
}
/* Open device */
fd = open(dfile2 ? dfile2 : dfile, O_RDONLY);
if (fd == -1) {
free(dfile2);
return 0;
}
/* Is this thing on... */
if (ioctl(fd, GET_ARRAY_INFO, &md)) {
fprintf(stderr,
_("Error getting MD array info from %s\n"),
dfile2 ? dfile2 : dfile);
exit(1);
}
close(fd);
free(dfile2);
/*
* Ignore levels we don't want aligned (e.g. linear)
* and deduct disk(s) from stripe width on RAID4/5/6
*/
switch (md.level) {
case 6:
md.raid_disks--;
/* fallthrough */
case 5:
case 4:
md.raid_disks--;
/* fallthrough */
case 1:
case 0:
case 10:
break;
default:
return 0;
}
/* Update sizes */
*sunit = md.chunk_size >> 9;
*swidth = *sunit * md.raid_disks;
*sectalign = (md.level == 4 || md.level == 5 || md.level == 6);
return 1;
}
return 0;
}