Skip to content

Commit 6c05da1

Browse files
Merge pull request #1159 from vojtechtrefny/master_dm-subsystem-libdevmapper
dm: Use libdevmapper instead of dmsetup to get subsystem from name
2 parents fabc60c + 80ba38c commit 6c05da1

File tree

4 files changed

+92
-21
lines changed

4 files changed

+92
-21
lines changed

src/lib/plugin_apis/dm.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ typedef enum {
1717
BD_DM_ERROR_RAID_FAIL,
1818
BD_DM_ERROR_RAID_NO_DEVS,
1919
BD_DM_ERROR_RAID_NO_EXIST,
20+
BD_DM_ERROR_DEVICE_NOEXIST,
2021
} BDDMError;
2122

2223
typedef enum {

src/plugins/dm.c

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
#include <glib.h>
21+
#include <string.h>
2122
#include <unistd.h>
2223
#include <blockdev/utils.h>
2324
#include <libdevmapper.h>
@@ -236,17 +237,61 @@ gchar* bd_dm_node_from_name (const gchar *map_name, GError **error) {
236237
* Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_QUERY
237238
*/
238239
gchar* bd_dm_get_subsystem_from_name (const gchar *device_name, GError **error) {
239-
gchar *output = NULL;
240-
gboolean success = FALSE;
241-
const gchar *argv[] = {"dmsetup", "info", "-co", "subsystem", "--noheadings", device_name, NULL};
240+
struct dm_task *task = NULL;
241+
struct dm_info info;
242+
const gchar *uuid = NULL;
243+
gchar *subsystem = NULL;
244+
gchar *hyphen_pos = NULL;
242245

243-
success = bd_utils_exec_and_capture_output (argv, NULL, &output, error);
244-
if (!success)
245-
/* error is already populated */
246+
task = dm_task_create (DM_DEVICE_INFO);
247+
if (!task) {
248+
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_TASK,
249+
"Failed to create DM task");
250+
return NULL;
251+
}
252+
253+
if (!dm_task_set_name (task, device_name)) {
254+
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_TASK,
255+
"Failed to set device name for DM task");
256+
dm_task_destroy (task);
246257
return NULL;
258+
}
259+
260+
if (!dm_task_run (task)) {
261+
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_TASK,
262+
"Failed to run DM task");
263+
dm_task_destroy (task);
264+
return NULL;
265+
}
247266

248-
output = g_strstrip (output);
249-
return output;
267+
if (!dm_task_get_info (task, &info)) {
268+
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_TASK,
269+
"Failed to get info from DM task");
270+
dm_task_destroy (task);
271+
return NULL;
272+
}
273+
274+
if (!info.exists) {
275+
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_DEVICE_NOEXIST,
276+
"DM device %s does not exist", device_name);
277+
dm_task_destroy (task);
278+
return NULL;
279+
}
280+
281+
uuid = dm_task_get_uuid (task);
282+
if (!uuid || !(*uuid)) {
283+
dm_task_destroy (task);
284+
return g_strdup ("");
285+
}
286+
287+
hyphen_pos = strchr (uuid, '-');
288+
if (hyphen_pos)
289+
subsystem = g_strndup (uuid, hyphen_pos - uuid);
290+
else
291+
subsystem = g_strdup ("");
292+
293+
dm_task_destroy (task);
294+
return subsystem;
250295
}
251296

252297
/**
@@ -270,12 +315,6 @@ gboolean bd_dm_map_exists (const gchar *map_name, gboolean live_only, gboolean a
270315
guint64 next = 0;
271316
gboolean ret = FALSE;
272317

273-
if (geteuid () != 0) {
274-
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_NOT_ROOT,
275-
"Not running as root, cannot query DM maps");
276-
return FALSE;
277-
}
278-
279318
task_list = dm_task_create (DM_DEVICE_LIST);
280319
if (!task_list) {
281320
g_set_error (error, BD_DM_ERROR, BD_DM_ERROR_TASK,

src/plugins/dm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ typedef enum {
1313
BD_DM_ERROR_RAID_FAIL,
1414
BD_DM_ERROR_RAID_NO_DEVS,
1515
BD_DM_ERROR_RAID_NO_EXIST,
16+
BD_DM_ERROR_DEVICE_NOEXIST,
1617
} BDDMError;
1718

1819
typedef enum {

tests/dm_test.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ def setUpClass(cls):
2222
else:
2323
BlockDev.reinit(cls.requested_plugins, True, None)
2424

25-
class DevMapperPluginVersionCase(DevMapperTest):
26-
@tag_test(TestTags.NOSTORAGE)
27-
def test_plugin_version(self):
28-
self.assertEqual(BlockDev.get_plugin_soname(BlockDev.Plugin.DM), "libbd_dm.so.3")
2925

3026
class DevMapperTestCase(DevMapperTest):
3127

@@ -51,6 +47,7 @@ def _clean_up(self):
5147

5248
os.unlink(self.dev_file)
5349

50+
5451
class DevMapperGetSubsystemFromName(DevMapperTestCase):
5552
def _destroy_lvm(self):
5653
run("vgremove --yes libbd_dm_tests --config \"devices {use_devicesfile = 0}\" >/dev/null 2>&1")
@@ -71,21 +68,51 @@ def test_get_subsystem_from_name_lvm(self):
7168
def test_get_subsystem_from_name_crypt(self):
7269
"""Verify that it is possible to get luks device subsystem from its name"""
7370
self.addCleanup(self._destroy_crypt)
74-
run("echo \"supersecretkey\" | cryptsetup luksFormat %s -" %self.loop_dev)
71+
run("echo \"supersecretkey\" | cryptsetup luksFormat --pbkdf=pbkdf2 --pbkdf-force-iterations=1000 %s -" %self.loop_dev)
7572
run("echo \"supersecretkey\" | cryptsetup open %s libbd_dm_tests-subsystem_crypt --key-file=-" %self.loop_dev)
7673
subsystem = BlockDev.dm_get_subsystem_from_name("libbd_dm_tests-subsystem_crypt")
7774
self.assertEqual(subsystem, "CRYPT")
7875

76+
77+
def test_get_subsystem_from_name_linear(self):
78+
succ = BlockDev.dm_create_linear("testMap", self.loop_dev, 100, None)
79+
self.assertTrue(succ)
80+
81+
# no UUID -- subsystem should be empty
82+
subsystem = BlockDev.dm_get_subsystem_from_name("testMap")
83+
self.assertEqual(subsystem, "")
84+
85+
succ = BlockDev.dm_remove("testMap")
86+
self.assertTrue(succ)
87+
88+
# "UUID" without "prefix" -- subsystem should be empty
89+
succ = BlockDev.dm_create_linear("testMap", self.loop_dev, 100, "TEST")
90+
self.assertTrue(succ)
91+
92+
subsystem = BlockDev.dm_get_subsystem_from_name("testMap")
93+
self.assertEqual(subsystem, "")
94+
95+
succ = BlockDev.dm_remove("testMap")
96+
self.assertTrue(succ)
97+
98+
# non-existing device --> error
99+
with self.assertRaisesRegex(GLib.GError, "does not exist"):
100+
BlockDev.dm_get_subsystem_from_name("testMap")
101+
102+
79103
class DevMapperCreateRemoveLinear(DevMapperTestCase):
80104
@tag_test(TestTags.CORE)
81105
def test_create_remove_linear(self):
82106
"""Verify that it is possible to create new linear mapping and remove it"""
83107

84108
succ = BlockDev.dm_create_linear("testMap", self.loop_dev, 100, None)
85109
self.assertTrue(succ)
110+
self.assertTrue(os.path.exists("/dev/mapper/testMap"))
86111

87112
succ = BlockDev.dm_remove("testMap")
88113
self.assertTrue(succ)
114+
self.assertFalse(os.path.exists("/dev/mapper/testMap"))
115+
89116

90117
class DevMapperMapExists(DevMapperTestCase):
91118
def test_map_exists(self):
@@ -115,6 +142,7 @@ def test_map_exists(self):
115142
succ = BlockDev.dm_map_exists("testMap", False, False)
116143
self.assertFalse(succ)
117144

145+
118146
class DevMapperNameNodeBijection(DevMapperTestCase):
119147
def test_name_node_bijection(self):
120148
"""Verify that the map's node and map name points to each other"""
@@ -125,9 +153,11 @@ def test_name_node_bijection(self):
125153
self.assertEqual(BlockDev.dm_name_from_node(BlockDev.dm_node_from_name("testMap")),
126154
"testMap")
127155

128-
self.assertTrue(succ)
129156

130-
class DMDepsTest(DevMapperTest):
157+
class DMNoStorageTest(DevMapperTest):
158+
@tag_test(TestTags.NOSTORAGE)
159+
def test_plugin_version(self):
160+
self.assertEqual(BlockDev.get_plugin_soname(BlockDev.Plugin.DM), "libbd_dm.so.3")
131161

132162
@tag_test(TestTags.NOSTORAGE)
133163
def test_missing_dependencies(self):

0 commit comments

Comments
 (0)