Skip to content

Commit

Permalink
Fix recursive locking in zfs_ioc_dataset_list_next_impl
Browse files Browse the repository at this point in the history
[257324.124447] VERIFY(!rrw_held(&dp->dp_config_rwlock, RW_READER)) failed
[257324.124450] PANIC at dsl_pool.c:1052:dsl_pool_config_enter()
[257324.124451] Showing stack for process 29206
[257324.124453] CPU: 6 PID: 29206 Comm: zfs Tainted: P           OE   4.1.3 #4
[257324.124454] Hardware name: Supermicro X10SAE/X10SAE, BIOS 3.0 05/20/2015
[257324.124455]  000000000000041c ffff88040c7aba88 ffffffff8161db7f 0000000080000000
[257324.124457]  ffffffffc0bf6238 ffff88040c7aba98 ffffffffc07f95c4 ffff88040c7abc28
[257324.124458]  ffffffffc07f968b ffff88040c7abb58 ffff8807e82f34e8 ffff880400000028
[257324.124459] Call Trace:
[257324.124465]  [<ffffffff8161db7f>] dump_stack+0x4f/0x7b
[257324.124484]  [<ffffffffc07f95c4>] spl_dumpstack+0x44/0x50 [spl]
[257324.124488]  [<ffffffffc07f968b>] spl_panic+0xbb/0x100 [spl]
[257324.124491]  [<ffffffff8108547d>] ? preempt_count_add+0x5d/0xb0
[257324.124492]  [<ffffffff810853e1>] ? get_parent_ip+0x11/0x50
[257324.124493]  [<ffffffff8108547d>] ? preempt_count_add+0x5d/0xb0
[257324.124495]  [<ffffffff816231cb>] ? _raw_spin_lock+0x1b/0x70
[257324.124496]  [<ffffffff81623237>] ? _raw_spin_unlock+0x17/0x30
[257324.124501]  [<ffffffffc07fd337>] ? tsd_hash_search.isra.0+0x77/0xa0 [spl]
[257324.124502]  [<ffffffff810853e1>] ? get_parent_ip+0x11/0x50
[257324.124503]  [<ffffffff8108547d>] ? preempt_count_add+0x5d/0xb0
[257324.124504]  [<ffffffff816231cb>] ? _raw_spin_lock+0x1b/0x70
[257324.124505]  [<ffffffff81623237>] ? _raw_spin_unlock+0x17/0x30
[257324.124525]  [<ffffffffc0b0e5d8>] dsl_pool_config_enter+0x68/0x70 [zfs]
[257324.124539]  [<ffffffffc0b10612>] dsl_pool_hold+0x42/0x50 [zfs]
[257324.124550]  [<ffffffffc0adfab6>] dmu_objset_hold+0x26/0xb0 [zfs]
[257324.124571]  [<ffffffffc0b7dca9>] zfs_ioc_objset_stats_impl.constprop.31+0x29/0x60 [zfs]
[257324.124589]  [<ffffffffc0b7e70d>] ? dataset_name_hidden+0x3d/0x50 [zfs]
[257324.124607]  [<ffffffffc0b7ec2b>] zfs_ioc_dataset_list_next_impl+0x12b/0x170 [zfs]
[257324.124626]  [<ffffffffc0b7ecf9>] zfs_ioc_list_next+0x89/0x280 [zfs]
[257324.124629]  [<ffffffffc07f1cec>] ? strdup+0x3c/0x70 [spl]
[257324.124646]  [<ffffffffc0b7ef20>] zfs_ioc_dataset_list_next+0x10/0x20 [zfs]
[257324.124664]  [<ffffffffc0b81b76>] zfsdev_ioctl+0x4e6/0x5b0 [zfs]
[257324.124666]  [<ffffffff811c2b90>] do_vfs_ioctl+0x2e0/0x4e0
[257324.124668]  [<ffffffff81253757>] ? file_has_perm+0x87/0xa0
[257324.124669]  [<ffffffff811c2e11>] SyS_ioctl+0x81/0xa0
[257324.124671]  [<ffffffff81623c5b>] system_call_fastpath+0x16/0x6e

Signed-off-by: Richard Yao <ryao@gentoo.org>
  • Loading branch information
ryao committed Jun 21, 2016
1 parent ea77ede commit 464c65d
Showing 1 changed file with 12 additions and 25 deletions.
37 changes: 12 additions & 25 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,7 @@ zfs_ioc_vdev_setfru(zfs_cmd_t *zc)
* The caller frees the nvlist on success.
*/
static int
zfs_ioc_objset_stats_impl_nohold(nvlist_t **nv, dmu_objset_stats_t *stat,
zfs_ioc_objset_stats_impl(nvlist_t **nv, dmu_objset_stats_t *stat,
objset_t *os, boolean_t str_indices)
{
int error = 0;
Expand Down Expand Up @@ -2189,25 +2189,6 @@ zfs_ioc_objset_stats_impl_nohold(nvlist_t **nv, dmu_objset_stats_t *stat,
return (error);
}

static int
zfs_ioc_objset_stats_impl(nvlist_t **nvp, dmu_objset_stats_t *stat,
char *fsname, boolean_t str_indices)
{
objset_t *os;
int error;

error = dmu_objset_hold(fsname, FTAG, &os);
if (error == 0) {
error = zfs_ioc_objset_stats_impl_nohold(nvp, stat,
os, str_indices);

dmu_objset_rele(os, FTAG);
}


return (error);
}

/*
* inputs:
* zc_name name of filesystem
Expand All @@ -2223,10 +2204,16 @@ zfs_ioc_objset_stats(zfs_cmd_t *zc)
{
nvlist_t *nv = NULL;
nvlist_t **nvp = (zc->zc_nvlist_dst) ? &nv : NULL;
objset_t *os;
int error;

error = zfs_ioc_objset_stats_impl(nvp, &zc->zc_objset_stats,
zc->zc_name, B_FALSE);
error = dmu_objset_hold(zc->zc_name, FTAG, &os);
if (error == 0) {
error = zfs_ioc_objset_stats_impl(nvp, &zc->zc_objset_stats,
os, B_FALSE);

dmu_objset_rele(os, FTAG);
}

if (nv) {
if (error == 0) {
Expand Down Expand Up @@ -2406,7 +2393,7 @@ zfs_ioc_dataset_list_next_impl(zfs_list_t *zl)
if (error == 0 && strchr(zl->zl_name, '$') == NULL) {
/* fill in the stats */
error = zfs_ioc_objset_stats_impl(&zl->zl_nvlist,
zl->zl_objset_stats, zl->zl_name, B_FALSE);
zl->zl_objset_stats, os, B_FALSE);
if (error == ENOENT) {
/* we lost a race with destroy, get the next one. */
zl->zl_name[orig_len] = '\0';
Expand Down Expand Up @@ -2464,7 +2451,7 @@ zfs_ioc_snapshot_list_next_impl(zfs_list_t *zl, boolean_t simple)

error = dmu_objset_from_ds(ds, &ossnap);
if (error == 0) {
error = zfs_ioc_objset_stats_impl_nohold(&nv,
error = zfs_ioc_objset_stats_impl(&nv,
zl->zl_objset_stats, ossnap, B_FALSE);
}
dsl_dataset_rele(ds, FTAG);
Expand Down Expand Up @@ -5984,7 +5971,7 @@ dump_ds(dsl_dataset_t *ds, const char *bmark, void *data)
goto out1;
}

err = zfs_ioc_objset_stats_impl_nohold(&nvl,
err = zfs_ioc_objset_stats_impl(&nvl,
&objset_stats, osp, B_TRUE);
if (err)
goto out1;
Expand Down

0 comments on commit 464c65d

Please sign in to comment.