Mercurial > illumos > git > illumos-omnios
changeset 23863:254c33369d8b
13194 null/dangling pointer deref somewhere under dmu_objset_upgrade
Portions contributed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Jerry Jelinek <gjelinek@gmail.com>
Approved by: Robert Mustacchi <rm@fingolfin.org>
author | Arkadiusz Bubała <arkadiusz.bubala@open-e.com> |
---|---|
date | Mon, 30 Nov 2020 19:21:29 +0000 |
parents | 352129d46a4b |
children | bbce4fbe98af |
files | usr/src/uts/common/fs/zfs/dmu_objset.c usr/src/uts/common/fs/zfs/zfs_ioctl.c usr/src/uts/common/fs/zfs/zfs_vfsops.c |
diffstat | 3 files changed, 25 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c Fri Dec 04 00:02:13 2020 +0200 +++ b/usr/src/uts/common/fs/zfs/dmu_objset.c Mon Nov 30 19:21:29 2020 +0000 @@ -28,6 +28,7 @@ * Copyright (c) 2015, STRATO AG, Inc. All rights reserved. * Copyright (c) 2014 Integros [integros.com] * Copyright 2017 Nexenta Systems, Inc. + * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -81,6 +82,8 @@ */ int dmu_rescan_dnode_threshold = 131072; +static char *upgrade_tag = "upgrade_tag"; + static void dmu_objset_find_dp_cb(void *arg); static void dmu_objset_upgrade(objset_t *os, dmu_objset_upgrade_cb_t cb); @@ -1484,6 +1487,7 @@ os->os_upgrade_exit = B_TRUE; os->os_upgrade_id = 0; mutex_exit(&os->os_upgrade_lock); + dsl_dataset_long_rele(dmu_objset_ds(os), upgrade_tag); } static void @@ -1492,6 +1496,9 @@ if (os->os_upgrade_id != 0) return; + ASSERT(dsl_pool_config_held(dmu_objset_pool(os))); + dsl_dataset_long_hold(dmu_objset_ds(os), upgrade_tag); + mutex_enter(&os->os_upgrade_lock); if (os->os_upgrade_id == 0 && os->os_upgrade_status == 0) { os->os_upgrade_exit = B_FALSE; @@ -1499,8 +1506,10 @@ os->os_upgrade_id = taskq_dispatch( os->os_spa->spa_upgrade_taskq, dmu_objset_upgrade_task_cb, os, TQ_SLEEP); - if (os->os_upgrade_id == 0) + if (os->os_upgrade_id == TASKQID_INVALID) { + dsl_dataset_long_rele(dmu_objset_ds(os), upgrade_tag); os->os_upgrade_status = ENOMEM; + } } mutex_exit(&os->os_upgrade_lock); } @@ -1511,10 +1520,12 @@ mutex_enter(&os->os_upgrade_lock); os->os_upgrade_exit = B_TRUE; if (os->os_upgrade_id != 0) { + taskqid_t tid = os->os_upgrade_id; + os->os_upgrade_id = 0; mutex_exit(&os->os_upgrade_lock); - taskq_wait(os->os_spa->spa_upgrade_taskq); + taskq_wait_id(os->os_spa->spa_upgrade_taskq, tid); } else { mutex_exit(&os->os_upgrade_lock); }
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Fri Dec 04 00:02:13 2020 +0200 +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Mon Nov 30 19:21:29 2020 +0000 @@ -5627,9 +5627,6 @@ if (error != 0) return (error); - dsl_dataset_long_hold(dmu_objset_ds(os), FTAG); - dsl_pool_rele(dmu_objset_pool(os), FTAG); - if (dmu_objset_userobjspace_upgradable(os) || dmu_objset_projectquota_upgradable(os)) { mutex_enter(&os->os_upgrade_lock); @@ -5643,11 +5640,14 @@ mutex_exit(&os->os_upgrade_lock); } + dsl_pool_rele(dmu_objset_pool(os), FTAG); + taskq_wait_id(os->os_spa->spa_upgrade_taskq, os->os_upgrade_id); error = os->os_upgrade_status; - } - - dsl_dataset_long_rele(dmu_objset_ds(os), FTAG); + } else { + dsl_pool_rele(dmu_objset_pool(os), FTAG); + } + dsl_dataset_rele(dmu_objset_ds(os), FTAG); return (error);
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c Fri Dec 04 00:02:13 2020 +0200 +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c Mon Nov 30 19:21:29 2020 +0000 @@ -924,8 +924,13 @@ int err; if (!dmu_objset_userobjspace_present(zfsvfs->z_os)) { - if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) + if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) { + dsl_pool_config_enter( + dmu_objset_pool(zfsvfs->z_os), FTAG); dmu_objset_id_quota_upgrade(zfsvfs->z_os); + dsl_pool_config_exit( + dmu_objset_pool(zfsvfs->z_os), FTAG); + } return (B_FALSE); }