Skip to content

Commit

Permalink
Fix invalid locking order in rename operation
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Richard Yao <[email protected]>
Signed-off-by: Tim Chase <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#2652.
Closes openzfs#2525.
  • Loading branch information
seletskiy authored and DHE committed Sep 18, 2014
1 parent 39f6568 commit 67f908e
Showing 1 changed file with 20 additions and 17 deletions.
37 changes: 20 additions & 17 deletions module/zfs/dsl_dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,9 +1612,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;
Expand All @@ -1641,18 +1638,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);
}
Expand Down Expand Up @@ -1680,15 +1665,33 @@ 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;
ddrsa.ddrsa_oldsnapname = oldsnapname;
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);
}

/*
Expand Down

0 comments on commit 67f908e

Please sign in to comment.