Fix invalid locking order in rename operation
This commit should prevent a deadlock on dp_config_rwlock when running `zfs rename` by ensuring zvol_rename_minors() is not called under this lock. Signed-off-by: Stanislav Seletskiy <s.seletskiy@gmail.com> Signed-off-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Tim Chase <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2652. Closes #2525.
This commit is contained in:
parent
4f6a14798d
commit
2078f21015
@ -1619,9 +1619,6 @@ static int
|
||||
dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
|
||||
dsl_dataset_t *hds, void *arg)
|
||||
{
|
||||
#ifdef _KERNEL
|
||||
char *oldname, *newname;
|
||||
#endif
|
||||
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
|
||||
dsl_dataset_t *ds;
|
||||
uint64_t val;
|
||||
@ -1648,18 +1645,6 @@ dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
|
||||
VERIFY0(zap_add(dp->dp_meta_objset, hds->ds_phys->ds_snapnames_zapobj,
|
||||
ds->ds_snapname, 8, 1, &ds->ds_object, tx));
|
||||
|
||||
#ifdef _KERNEL
|
||||
oldname = kmem_alloc(MAXPATHLEN, KM_PUSHPAGE);
|
||||
newname = kmem_alloc(MAXPATHLEN, KM_PUSHPAGE);
|
||||
snprintf(oldname, MAXPATHLEN, "%s@%s", ddrsa->ddrsa_fsname,
|
||||
ddrsa->ddrsa_oldsnapname);
|
||||
snprintf(newname, MAXPATHLEN, "%s@%s", ddrsa->ddrsa_fsname,
|
||||
ddrsa->ddrsa_newsnapname);
|
||||
zvol_rename_minors(oldname, newname);
|
||||
kmem_free(newname, MAXPATHLEN);
|
||||
kmem_free(oldname, MAXPATHLEN);
|
||||
#endif
|
||||
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (0);
|
||||
}
|
||||
@ -1687,6 +1672,11 @@ int
|
||||
dsl_dataset_rename_snapshot(const char *fsname,
|
||||
const char *oldsnapname, const char *newsnapname, boolean_t recursive)
|
||||
{
|
||||
#ifdef _KERNEL
|
||||
char *oldname, *newname;
|
||||
#endif
|
||||
int error;
|
||||
|
||||
dsl_dataset_rename_snapshot_arg_t ddrsa;
|
||||
|
||||
ddrsa.ddrsa_fsname = fsname;
|
||||
@ -1694,8 +1684,21 @@ dsl_dataset_rename_snapshot(const char *fsname,
|
||||
ddrsa.ddrsa_newsnapname = newsnapname;
|
||||
ddrsa.ddrsa_recursive = recursive;
|
||||
|
||||
return (dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
|
||||
dsl_dataset_rename_snapshot_sync, &ddrsa, 1));
|
||||
error = dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
|
||||
dsl_dataset_rename_snapshot_sync, &ddrsa, 1);
|
||||
|
||||
if (error)
|
||||
return (SET_ERROR(error));
|
||||
|
||||
#ifdef _KERNEL
|
||||
oldname = kmem_asprintf("%s@%s", fsname, oldsnapname);
|
||||
newname = kmem_asprintf("%s@%s", fsname, newsnapname);
|
||||
zvol_rename_minors(oldname, newname);
|
||||
strfree(newname);
|
||||
strfree(oldname);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user