diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c index 19b663e3ec0a..3dd59bcc43bc 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c @@ -2312,6 +2312,7 @@ dsl_dataset_snapshot_rename_check(void *arg1, void *arg2, dmu_tx_t *tx) static void dsl_dataset_snapshot_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx) { + char oldname[MAXPATHLEN], newname[MAXPATHLEN]; dsl_dataset_t *ds = arg1; const char *newsnapname = arg2; dsl_dir_t *dd = ds->ds_dir; @@ -2327,12 +2328,15 @@ dsl_dataset_snapshot_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx) VERIFY(0 == dsl_dataset_get_snapname(ds)); err = dsl_dataset_snap_remove(hds, ds->ds_snapname, tx); ASSERT3U(err, ==, 0); + dsl_dataset_name(ds, oldname); mutex_enter(&ds->ds_lock); (void) strcpy(ds->ds_snapname, newsnapname); mutex_exit(&ds->ds_lock); err = zap_add(mos, hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname, 8, 1, &ds->ds_object, tx); ASSERT3U(err, ==, 0); + dsl_dataset_name(ds, newname); + zvol_rename_minors(oldname, newname); spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx, "dataset = %llu", ds->ds_object); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c index 1cd49c8274e8..79f45f260554 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "zfs_namecheck.h" static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd); @@ -1294,6 +1295,7 @@ dsl_dir_rename_check(void *arg1, void *arg2, dmu_tx_t *tx) static void dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx) { + char oldname[MAXPATHLEN], newname[MAXPATHLEN]; dsl_dir_t *dd = arg1; struct renamearg *ra = arg2; dsl_pool_t *dp = dd->dd_pool; @@ -1326,6 +1328,7 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx) dmu_buf_will_dirty(dd->dd_dbuf, tx); /* remove from old parent zapobj */ + dsl_dir_name(dd, oldname); err = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx); ASSERT3U(err, ==, 0); @@ -1340,6 +1343,8 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx) err = zap_add(mos, ra->newparent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, 8, 1, &dd->dd_object, tx); ASSERT3U(err, ==, 0); + dsl_dir_name(dd, newname); + zvol_rename_minors(oldname, newname); spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx, "dataset = %llu", dd->dd_phys->dd_head_dataset_obj); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h index c0a0a69f71ca..4da5b84d7196 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h @@ -73,6 +73,7 @@ extern void zvol_log_write_minor(void *minor_hdl, dmu_tx_t *tx, offset_t off, #ifdef __FreeBSD__ extern int zvol_create_minors(const char *name); +extern void zvol_rename_minors(const char *oldname, const char *newname); #endif #endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 52300ee442e1..153f957031cc 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -3271,8 +3271,6 @@ zfs_ioc_rename(zfs_cmd_t *zc) if (err) return (err); } - if (zc->zc_objset_type == DMU_OST_ZVOL) - (void) zvol_remove_minor(zc->zc_name); return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c index 8c593d2c22aa..a514247321ac 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c @@ -2223,3 +2223,70 @@ zvol_create_minors(const char *name) kmem_free(osname, MAXPATHLEN); return (0); } + +static void +zvol_rename_minor(struct g_geom *gp, const char *newname) +{ + struct g_provider *pp; + zvol_state_t *zv; + + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); + g_topology_assert(); + + pp = LIST_FIRST(&gp->provider); + ASSERT(pp != NULL); + zv = pp->private; + ASSERT(zv != NULL); + + zv->zv_provider = NULL; + g_wither_provider(pp, ENXIO); + + pp = g_new_providerf(gp, "%s/%s", ZVOL_DRIVER, newname); + pp->sectorsize = DEV_BSIZE; + pp->mediasize = zv->zv_volsize; + pp->private = zv; + zv->zv_provider = pp; + strlcpy(zv->zv_name, newname, sizeof(zv->zv_name)); + g_error_provider(pp, 0); +} + +void +zvol_rename_minors(const char *oldname, const char *newname) +{ + char name[MAXPATHLEN]; + struct g_provider *pp; + struct g_geom *gp; + size_t oldnamelen, newnamelen; + zvol_state_t *zv; + char *namebuf; + + oldnamelen = strlen(oldname); + newnamelen = strlen(newname); + + DROP_GIANT(); + mutex_enter(&zfsdev_state_lock); + g_topology_lock(); + + LIST_FOREACH(gp, &zfs_zvol_class.geom, geom) { + pp = LIST_FIRST(&gp->provider); + if (pp == NULL) + continue; + zv = pp->private; + if (zv == NULL) + continue; + if (strcmp(zv->zv_name, oldname) == 0) { + zvol_rename_minor(gp, newname); + } else if (strncmp(zv->zv_name, oldname, oldnamelen) == 0 && + (zv->zv_name[oldnamelen] == '/' || + zv->zv_name[oldnamelen] == '@')) { + snprintf(name, sizeof(name), "%s%c%s", newname, + zv->zv_name[oldnamelen], + zv->zv_name + oldnamelen + 1); + zvol_rename_minor(gp, name); + } + } + + g_topology_unlock(); + mutex_exit(&zfsdev_state_lock); + PICKUP_GIANT(); +}