From 3cb820632a13a91e0c2e579aedbe8e86b4f0040e Mon Sep 17 00:00:00 2001 From: Phillip Susi Date: Fri, 19 Oct 2012 17:32:00 +0200 Subject: [PATCH 47/89] libparted: don't probe every dm device in probe_all We were probing every dm device. Only probe dmraid whole disk (non-partition) devices instead. This removes the clutter of LVM logical volumes, and dmraid partitions from the list, which usually do not make sense to partition. * NEWS (Changes in behavior): Mention it. * libparted/arch/linux.c (_is_dmraid_device): New function. (_dm_is_part): Likewise. (_probe_dm_devices): Use the latter. * tests/t6003-dm-hide.sh: New test. * tests/Makefile.am (TESTS): Add it. --- NEWS | 3 ++ libparted/arch/linux.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++- tests/Makefile.am | 1 + tests/t6003-dm-hide.sh | 60 +++++++++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 tests/t6003-dm-hide.sh diff --git a/NEWS b/NEWS index a40d69b..89541fd 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,9 @@ GNU parted NEWS -*- outline -*- ** Changes in behavior + parted -l no longer lists device-mapper devices other than + dmraid whole disks. + Added new Linux-specific partition GUID type code (0FC63DAF-8483-4772-8E79-3D69D8477DE4) for Linux filesystem data on GPT disks. This type code is now assigned as the default partition type code diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c index 5721d4b..083591f 100644 --- a/libparted/arch/linux.c +++ b/libparted/arch/linux.c @@ -65,6 +65,8 @@ # define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ #endif +#define STRPREFIX(a, b) (strncmp (a, b, strlen (b)) == 0) + #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #ifndef __NR__llseek @@ -478,6 +480,82 @@ bad: return r; } +/* Return nonzero if device-mapper device, DEVPATH, is part of a dmraid + array. Use the heuristic of checking for the string "DMRAID-" at the + start of its UUID. */ +static int +_is_dmraid_device (const char *devpath) +{ + int rc = 0; + + char const *dm_name = strrchr (devpath, '/'); + char const *dm_basename = dm_name && *(++dm_name) ? dm_name : devpath; + struct dm_task *task = dm_task_create (DM_DEVICE_DEPS); + if (!task) + return 0; + + dm_task_set_name (task, dm_basename); + if (!dm_task_run (task)) + goto err; + + const char *dmraid_uuid = dm_task_get_uuid (task); + if (STRPREFIX (dmraid_uuid, "DMRAID-")) + rc = 1; + +err: + dm_task_destroy (task); + return rc; +} + +/* We consider a dm device that is a linear mapping with a * + * single target that also is a dm device to be a partition */ + +static int +_dm_is_part (const char *path) +{ + int rc = 0; + struct dm_task *task = dm_task_create (DM_DEVICE_DEPS); + if (!task) + return 0; + + dm_task_set_name(task, path); + if (!dm_task_run(task)) + goto err; + + struct dm_info *info = alloca (sizeof *info); + memset(info, '\0', sizeof *info); + dm_task_get_info (task, info); + if (!info->exists) + goto err; + + struct dm_deps *deps = dm_task_get_deps (task); + if (!deps) + goto err; + + if (deps->count != 1) + goto err; + if (!_is_dm_major (major (deps->device[0]))) + goto err; + dm_task_destroy (task); + if (!(task = dm_task_create (DM_DEVICE_TABLE))) + return 0; + dm_task_set_name (task, path); + if (!dm_task_run (task)) + goto err; + + char *target_type = NULL; + char *params = NULL; + uint64_t start, length; + + dm_get_next_target (task, NULL, &start, &length, &target_type, ¶ms); + if (strcmp (target_type, "linear")) + goto err; + rc = 1; + +err: + dm_task_destroy(task); + return rc; +} static int _probe_dm_devices () @@ -504,7 +582,8 @@ _probe_dm_devices () if (stat (buf, &st) != 0) continue; - if (_is_dm_major(major(st.st_rdev))) + if (_is_dm_major(major(st.st_rdev)) && _is_dmraid_device (buf) + && !_dm_is_part(buf)) _ped_device_probe (buf); } closedir (mapper_dir); diff --git a/tests/Makefile.am b/tests/Makefile.am index 4649c0a..4ec08da 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -59,6 +59,7 @@ TESTS = \ t6000-dm.sh \ t6001-psep.sh \ t6002-dm-busy.sh \ + t6003-dm-hide.sh \ t6100-mdraid-partitions.sh \ t7000-scripting.sh \ t8000-loop.sh \ diff --git a/tests/t6003-dm-hide.sh b/tests/t6003-dm-hide.sh new file mode 100644 index 0000000..3cfdc43 --- /dev/null +++ b/tests/t6003-dm-hide.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# ensure that parted -l only shows dmraid device-mapper devices + +# Copyright (C) 2008-2012 Free Software Foundation, Inc. + +# 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; either version 3 of the License, or +# (at your option) any later version. + +# This program 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 this program. If not, see . + +. "${srcdir=.}/init.sh"; path_prepend_ ../parted + +require_root_ +lvm_init_root_dir_ + +test "x$ENABLE_DEVICE_MAPPER" = xyes \ + || skip_ "no device-mapper support" + +# Device maps names - should be random to not conflict with existing ones on +# the system +linear_=plinear-$$ + +d1= +f1= +dev= +cleanup_fn_() { + dmsetup remove $linear_ + test -n "$d1" && losetup -d "$d1" + rm -f "$f1" +} + +f1=$(pwd)/1; d1=$(loop_setup_ "$f1") \ + || fail=1 + +# setup: create a mapping +echo "0 2048 linear $d1 0" | dmsetup create $linear_ || fail=1 +dev="$DM_DEV_DIR/mapper/$linear_" + +# device should not show up + +parted -l >out 2>&1 +! grep $linear_ out || fail=1 + +dmsetup remove $linear_ +echo "0 2048 linear $d1 0" | dmsetup create $linear_ -u "DMRAID-fake" || fail=1 + +# device should now show up + +parted -l >out 2>&1 +grep $linear_ out || fail=1 + +Exit $fail -- 1.8.5.3