diff options
| author | christos <christos@NetBSD.org> | 2018-01-05 14:22:05 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2018-01-05 14:22:05 +0000 |
| commit | c4e2c478b3916d5df219d75b5cdc6a3dec1ba0cd (patch) | |
| tree | 9841ebc22ba456ee2faaec4027b1e1e3c68799b7 | |
| parent | 09179cfedd4b4ab3de234f3fdc319b29d5e03718 (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.c | 19 | ||||
| -rw-r--r-- | sys/dev/dm/dm_target_linear.c | 28 | ||||
| -rw-r--r-- | sys/dev/dm/dm_target_snapshot.c | 45 |
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) |
