1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-28 16:43:09 +00:00

Make renaming of a ZVOL, ZVOL's parent directory and ZVOL snapshot work.

Reported by:	avg
MFC after:	1 month
This commit is contained in:
Pawel Jakub Dawidek 2011-03-05 22:31:03 +00:00
parent 5bf0660559
commit 2348f1110e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219317
5 changed files with 77 additions and 2 deletions

View File

@ -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);

View File

@ -36,6 +36,7 @@
#include <sys/zio.h>
#include <sys/arc.h>
#include <sys/sunddi.h>
#include <sys/zvol.h>
#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);

View File

@ -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

View File

@ -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));
}

View File

@ -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();
}