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:
parent
5bf0660559
commit
2348f1110e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219317
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user