summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2018-01-05 14:22:05 +0000
committerchristos <christos@NetBSD.org>2018-01-05 14:22:05 +0000
commitc4e2c478b3916d5df219d75b5cdc6a3dec1ba0cd (patch)
tree9841ebc22ba456ee2faaec4027b1e1e3c68799b7
parent09179cfedd4b4ab3de234f3fdc319b29d5e03718 (diff)
PR/52900: Tomohiro Kusumi: Fix kernel panic when target's ->init() failed
Reliably unbusy the target in the *all* the destroy routines, so ioctl does not need to do it.
-rw-r--r--sys/dev/dm/dm_ioctl.c19
-rw-r--r--sys/dev/dm/dm_target_linear.c28
-rw-r--r--sys/dev/dm/dm_target_snapshot.c45
3 files changed, 60 insertions, 32 deletions
diff --git a/sys/dev/dm/dm_ioctl.c b/sys/dev/dm/dm_ioctl.c
index 04040b2f9a2..36078ec2c04 100644
--- a/sys/dev/dm/dm_ioctl.c
+++ b/sys/dev/dm/dm_ioctl.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dm_ioctl.c,v 1.31 2017/06/01 02:45:09 chs Exp $ */
+/* $NetBSD: dm_ioctl.c,v 1.32 2018/01/05 14:22:05 christos Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -28,6 +28,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: dm_ioctl.c,v 1.32 2018/01/05 14:22:05 christos Exp $");
/*
* Locking is used to synchronise between ioctl calls and between dm_table's
@@ -158,6 +160,7 @@ dm_dbg_print_flags(int flags)
return 0;
}
+
/*
* Get version ioctl call I do it as default therefore this
* function is unused now.
@@ -168,6 +171,7 @@ dm_get_version_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Get list of all available targets from global
* target list and sent them back to libdevmapper.
@@ -190,6 +194,7 @@ dm_list_versions_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Create in-kernel entry for device. Device attributes such as name, uuid are
* taken from proplib dictionary.
@@ -271,6 +276,7 @@ dm_dev_create_ioctl(prop_dictionary_t dm_dict)
return r;
}
+
/*
* Get list of created device-mapper devices fromglobal list and
* send it to kernel.
@@ -309,6 +315,7 @@ dm_dev_list_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Rename selected devices old name is in struct dm_ioctl.
* newname is taken from dictionary
@@ -366,6 +373,7 @@ dm_dev_rename_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Remove device from global list I have to remove active
* and inactive tables first.
@@ -408,6 +416,7 @@ dm_dev_remove_ioctl(prop_dictionary_t dm_dict)
*/
return config_detach(devt, DETACH_QUIET);
}
+
/*
* Return actual state of device to libdevmapper.
*/
@@ -461,6 +470,7 @@ dm_dev_status_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Set only flag to suggest that device is suspended. This call is
* not supported in NetBSD.
@@ -501,6 +511,7 @@ dm_dev_suspend_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Simulate Linux behaviour better and switch tables here and not in
* dm_table_load_ioctl.
@@ -551,6 +562,7 @@ dm_dev_resume_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Table management routines
* lvm2tools doens't send name/uuid to kernel with table
@@ -596,6 +608,7 @@ dm_table_clear_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Get list of physical devices for active table.
* Get dev_t from pdev vnode and insert it into cmd_array.
@@ -661,6 +674,7 @@ dm_table_deps_ioctl(prop_dictionary_t dm_dict)
return 0;
}
+
/*
* Load new table/tables to device.
* Call apropriate target init routine open all physical pdev's and
@@ -788,7 +802,6 @@ dm_table_load_ioctl(prop_dictionary_t dm_dict)
free(str, M_TEMP);
dm_dev_unbusy(dmv);
- dm_target_unbusy(target);
prop_object_iterator_release(iter);
return ret;
}
@@ -804,6 +817,7 @@ dm_table_load_ioctl(prop_dictionary_t dm_dict)
dm_dev_unbusy(dmv);
return 0;
}
+
/*
* Get description of all tables loaded to device from kernel
* and send it to libdevmapper.
@@ -935,7 +949,6 @@ dm_table_status_ioctl(prop_dictionary_t dm_dict)
return 0;
}
-
/*
* For every call I have to set kernel driver version.
* Because I can have commands supported only in other
diff --git a/sys/dev/dm/dm_target_linear.c b/sys/dev/dm/dm_target_linear.c
index 49f309268b8..a41da561480 100644
--- a/sys/dev/dm/dm_target_linear.c
+++ b/sys/dev/dm/dm_target_linear.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dm_target_linear.c,v 1.16 2017/06/04 08:54:38 mbalmer Exp $ */
+/* $NetBSD: dm_target_linear.c,v 1.17 2018/01/05 14:22:05 christos Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -28,7 +28,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: dm_target_linear.c,v 1.17 2018/01/05 14:22:05 christos Exp $");
/*
* This file implements initial version of device-mapper dklinear target.
@@ -95,6 +96,7 @@ dm_target_linear_init(dm_dev_t * dmv, void **target_config, char *params)
return 0;
}
+
/*
* Status routine is called to get params string, which is target
* specific. When dm_table_status_ioctl is called with flag
@@ -118,6 +120,7 @@ dm_target_linear_status(void *target_config)
return params;
}
+
/*
* Do IO operation, called from dmstrategy routine.
*/
@@ -138,6 +141,7 @@ dm_target_linear_strategy(dm_table_entry_t * table_en, struct buf * bp)
return 0;
}
+
/*
* Sync underlying disk caches.
*/
@@ -154,36 +158,35 @@ dm_target_linear_sync(dm_table_entry_t * table_en)
return VOP_IOCTL(tlc->pdev->pdev_vnode, DIOCCACHESYNC, &cmd,
FREAD|FWRITE, kauth_cred_get());
}
+
/*
* Destroy target specific data. Decrement table pdevs.
*/
int
dm_target_linear_destroy(dm_table_entry_t * table_en)
{
- dm_target_linear_config_t *tlc;
/*
* Destroy function is called for every target even if it
* doesn't have target_config.
*/
-
if (table_en->target_config == NULL)
- return 0;
+ goto out;
- tlc = table_en->target_config;
+ dm_target_linear_config_t *tlc = table_en->target_config;
+ table_en->target_config = NULL;
/* Decrement pdev ref counter if 0 remove it */
dm_pdev_decr(tlc->pdev);
+ kmem_free(tlc, sizeof(*tlc));
+
+out:
/* Unbusy target so we can unload it */
dm_target_unbusy(table_en->target);
-
- kmem_free(table_en->target_config, sizeof(dm_target_linear_config_t));
-
- table_en->target_config = NULL;
-
return 0;
}
+
/* Add this target pdev dependencies to prop_array_t */
int
dm_target_linear_deps(dm_table_entry_t * table_en, prop_array_t prop_array)
@@ -200,6 +203,7 @@ dm_target_linear_deps(dm_table_entry_t * table_en, prop_array_t prop_array)
return 0;
}
+
/*
* Register upcall device.
* Linear target doesn't need any upcall devices but other targets like
@@ -210,6 +214,7 @@ dm_target_linear_upcall(dm_table_entry_t * table_en, struct buf * bp)
{
return 0;
}
+
/*
* Query physical block size of this target
* For a linear target this is just the sector size of the underlying device
@@ -230,6 +235,7 @@ dm_target_linear_secsize(dm_table_entry_t * table_en, unsigned *secsizep)
return 0;
}
+
/*
* Transform char s to uint64_t offset number.
*/
diff --git a/sys/dev/dm/dm_target_snapshot.c b/sys/dev/dm/dm_target_snapshot.c
index fe88ea1ed54..f631331860b 100644
--- a/sys/dev/dm/dm_target_snapshot.c
+++ b/sys/dev/dm/dm_target_snapshot.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dm_target_snapshot.c,v 1.18 2017/06/04 08:54:38 mbalmer Exp $ */
+/* $NetBSD: dm_target_snapshot.c,v 1.19 2018/01/05 14:22:05 christos Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -28,6 +28,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: dm_target_snapshot.c,v 1.19 2018/01/05 14:22:05 christos Exp $");
/*
* 1. Suspend my_data to temporarily stop any I/O while the snapshot is being
@@ -248,6 +250,7 @@ dm_target_snapshot_init(dm_dev_t * dmv, void **target_config, char *params)
return 0;
}
+
/*
* Status routine is called to get params string, which is target
* specific. When dm_table_status_ioctl is called with flag
@@ -296,6 +299,7 @@ dm_target_snapshot_status(void *target_config)
return params;
}
+
/* Strategy routine called from dm_strategy. */
int
dm_target_snapshot_strategy(dm_table_entry_t * table_en, struct buf * bp)
@@ -310,39 +314,37 @@ dm_target_snapshot_strategy(dm_table_entry_t * table_en, struct buf * bp)
return 0;
}
+
/* Doesn't do anything here. */
int
dm_target_snapshot_destroy(dm_table_entry_t * table_en)
{
- dm_target_snapshot_config_t *tsc;
/*
* Destroy function is called for every target even if it
* doesn't have target_config.
*/
-
if (table_en->target_config == NULL)
- return 0;
+ goto out;
printf("Snapshot target destroy function called\n");
- tsc = table_en->target_config;
+ dm_target_snapshot_config_t *tsc = table_en->target_config;
+ table_en->target_config = NULL;
/* Decrement pdev ref counter if 0 remove it */
dm_pdev_decr(tsc->tsc_snap_dev);
-
if (tsc->tsc_persistent_dev)
dm_pdev_decr(tsc->tsc_cow_dev);
+ kmem_free(tsc, sizeof(*tsc));
+out:
/* Unbusy target so we can unload it */
dm_target_unbusy(table_en->target);
- kmem_free(table_en->target_config, sizeof(dm_target_snapshot_config_t));
-
- table_en->target_config = NULL;
-
return 0;
}
+
/* Add this target dependencies to prop_array_t */
int
dm_target_snapshot_deps(dm_table_entry_t * table_en,
@@ -365,6 +367,7 @@ dm_target_snapshot_deps(dm_table_entry_t * table_en,
}
return 0;
}
+
/* Upcall is used to inform other depended devices about IO. */
int
dm_target_snapshot_upcall(dm_table_entry_t * table_en, struct buf * bp)
@@ -377,6 +380,7 @@ dm_target_snapshot_upcall(dm_table_entry_t * table_en, struct buf * bp)
return 0;
}
+
/*
* dm target snapshot origin routines.
*
@@ -419,6 +423,7 @@ dm_target_snapshot_orig_init(dm_dev_t * dmv, void **target_config, char *params)
return 0;
}
+
/*
* Status routine is called to get params string, which is target
* specific. When dm_table_status_ioctl is called with flag
@@ -452,6 +457,7 @@ dm_target_snapshot_orig_status(void *target_config)
return params;
}
+
/* Strategy routine called from dm_strategy. */
int
dm_target_snapshot_orig_strategy(dm_table_entry_t * table_en, struct buf * bp)
@@ -466,6 +472,7 @@ dm_target_snapshot_orig_strategy(dm_table_entry_t * table_en, struct buf * bp)
return 0;
}
+
/*
* Sync underlying disk caches.
*/
@@ -479,13 +486,14 @@ dm_target_snapshot_orig_sync(dm_table_entry_t * table_en)
cmd = 1;
- return VOP_IOCTL(tsoc->tsoc_real_dev->pdev_vnode, DIOCCACHESYNC, &cmd, FREAD|FWRITE, kauth_cred_get());
+ return VOP_IOCTL(tsoc->tsoc_real_dev->pdev_vnode, DIOCCACHESYNC,
+ &cmd, FREAD|FWRITE, kauth_cred_get());
}
+
/* Decrement pdev and free allocated space. */
int
dm_target_snapshot_orig_destroy(dm_table_entry_t * table_en)
{
- dm_target_snapshot_origin_config_t *tsoc;
/*
* Destroy function is called for every target even if it
@@ -493,22 +501,22 @@ dm_target_snapshot_orig_destroy(dm_table_entry_t * table_en)
*/
if (table_en->target_config == NULL)
- return 0;
+ goto out;
- tsoc = table_en->target_config;
+ dm_target_snapshot_origin_config_t *tsoc = table_en->target_config;
+ table_en->target_config = NULL;
/* Decrement pdev ref counter if 0 remove it */
dm_pdev_decr(tsoc->tsoc_real_dev);
+ kmem_free(tsoc, sizeof(*tsoc));
+out:
/* Unbusy target so we can unload it */
dm_target_unbusy(table_en->target);
- kmem_free(table_en->target_config, sizeof(dm_target_snapshot_origin_config_t));
-
- table_en->target_config = NULL;
-
return 0;
}
+
/*
* Get target deps and add them to prop_array_t.
*/
@@ -537,6 +545,7 @@ dm_target_snapshot_orig_deps(dm_table_entry_t * table_en,
return 0;
}
+
/* Unsupported for this target. */
int
dm_target_snapshot_orig_upcall(dm_table_entry_t * table_en, struct buf * bp)