Skip to content

Commit

Permalink
[TA2335]Create snapshot and clone for rebuild, the moment data connec…
Browse files Browse the repository at this point in the history
…tion is created. (openzfs#108)

Signed-off-by: satbir <satbir.chhikara@gmail.com>
  • Loading branch information
satbirchhikara authored and vishnuitta committed Sep 13, 2018
1 parent cc8484d commit fa100c7
Show file tree
Hide file tree
Showing 12 changed files with 548 additions and 325 deletions.
11 changes: 7 additions & 4 deletions include/uzfs_rebuilding.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,14 @@ int uzfs_get_io_diff(zvol_state_t *zv, blk_metadata_t *base_metadata,
int uzfs_get_nonoverlapping_ondisk_blks(zvol_state_t *zv, uint64_t offset,
uint64_t len, blk_metadata_t *incoming_md, void **list);
int
uzfs_zvol_create_snaprebuild_clone(zvol_state_t *zv,
zvol_state_t **snap_zv);
uzfs_zvol_get_or_create_internal_clone(zvol_state_t *zv,
zvol_state_t **snap_zv, zvol_state_t **clone_zv, int *ret_val);
int
uzfs_zvol_destroy_snaprebuild_clone(zvol_state_t *zv,
zvol_state_t *snap_zv);
uzfs_zvol_release_internal_clone(zvol_state_t *zv,
zvol_state_t **snap_zv, zvol_state_t **clone_zv);
int
uzfs_zvol_destroy_internal_clone(zvol_state_t *zv,
zvol_state_t **snap_zv, zvol_state_t **clone_zv);
#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 4 additions & 2 deletions include/zrepl_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ typedef struct zvol_info_s {
/* Logical Unit related fields */
zvol_info_state_t state;
char name[MAXPATHLEN];
zvol_state_t *zv;
zvol_state_t *main_zv;
zvol_state_t *clone_zv;
zvol_state_t *snap_zv;
uint64_t refcnt;

union {
Expand Down Expand Up @@ -172,7 +174,7 @@ typedef struct zinfo_fd_s {
typedef struct zvol_io_cmd_s {
STAILQ_ENTRY(zvol_io_cmd_s) cmd_link;
zvol_io_hdr_t hdr;
void *zv;
zvol_info_t *zinfo;
void *buf;
uint64_t buf_len;
metadata_desc_t *metadata_desc;
Expand Down
29 changes: 29 additions & 0 deletions lib/libzpool/uzfs_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <uzfs_mgmt.h>
#include <uzfs_io.h>
#include <uzfs_zap.h>
#include <uzfs_rebuilding.h>

static int uzfs_fd_rand = -1;
kmutex_t zvol_list_mutex;
Expand Down Expand Up @@ -462,6 +463,26 @@ uzfs_create_dataset(spa_t *spa, char *ds_name, uint64_t vol_size,
return (error);
}

/*
* This function is checked if volume is internally
* created cloned volume for rebuild purpose.
* Input: Volume name [pool/volume_name].
* Output: 0 if volume is internally created cloned volume.
* Otherwise non-zero value.
*/
int
is_internally_created_clone_volume(const char *ds_name)
{
size_t ds_len = strlen(ds_name);
size_t pattern_len = strlen(REBUILD_SNAPSHOT_CLONENAME);

if (ds_len < pattern_len)
return (-1);

return (strcmp(ds_name + (ds_len - pattern_len),
REBUILD_SNAPSHOT_CLONENAME));
}

/* uZFS Zvol create call back function */
int
uzfs_zvol_create_cb(const char *ds_name, void *arg)
Expand All @@ -475,6 +496,14 @@ uzfs_zvol_create_cb(const char *ds_name, void *arg)
return (0);
}

/*
* Internally created cloned volume do not have target IP stored
* infact they do not need to have zinfo and connection to target
* as these are not meant for client/application.
*/
if (is_internally_created_clone_volume(ds_name) == 0)
return (0);

error = uzfs_dataset_zv_create(ds_name, &zv);
if (error) {
/* happens normally for all non-zvol-type datasets */
Expand Down
107 changes: 98 additions & 9 deletions lib/libzpool/uzfs_rebuilding.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,22 +317,75 @@ uzfs_get_nonoverlapping_ondisk_blks(zvol_state_t *zv, uint64_t offset,
return (count);
}

/*
* This API is used to release internal clone dataset
*/
int
uzfs_zvol_destroy_snaprebuild_clone(zvol_state_t *zv,
zvol_state_t *snap_zv)
uzfs_zvol_release_internal_clone(zvol_state_t *zv,
zvol_state_t **snap_zv, zvol_state_t **clone_zv)
{
int ret = 0;
char *clonename;

if (*snap_zv == NULL) {
ASSERT(*clone_zv == NULL);
return (ret);
}

clonename = kmem_asprintf("%s/%s_%s", spa_name(zv->zv_spa),
strchr(zv->zv_name, '/') + 1,
REBUILD_SNAPSHOT_CLONENAME);

/* Close dataset */
uzfs_close_dataset(snap_zv);
LOG_INFO("Closing rebuild_snap and rebuild_clone dataset on:%s",
zv->zv_name);
/* Close clone dataset */
uzfs_close_dataset(*clone_zv);
*clone_zv = NULL;

/* Close snapshot dataset */
uzfs_close_dataset(*snap_zv);
*snap_zv = NULL;

strfree(clonename);

return (ret);
}

/*
* This API is used to delete internal
* cloned volume and backing snapshot.
*/
int
uzfs_zvol_destroy_internal_clone(zvol_state_t *zv,
zvol_state_t **snap_zv, zvol_state_t **clone_zv)
{
int ret = 0;
char *clonename;

if (*snap_zv == NULL) {
ASSERT(*clone_zv == NULL);
return (ret);
}

clonename = kmem_asprintf("%s/%s_%s", spa_name(zv->zv_spa),
strchr(zv->zv_name, '/') + 1,
REBUILD_SNAPSHOT_CLONENAME);

/* Close clone dataset */
uzfs_close_dataset(*clone_zv);
*clone_zv = NULL;
LOG_INFO("Destroying rebuild_snap and rebuild_clone on:%s",
zv->zv_name);

/* Destroy clone */
ret = dsl_destroy_head(clonename);
if (ret != 0)
LOG_ERRNO("Rebuild_clone destroy failed on:%s"
" with err:%d", zv->zv_name, ret);

/* Close snapshot dataset */
uzfs_close_dataset(*snap_zv);
*snap_zv = NULL;

/* Destroy snapshot */
destroy_snapshot_zv(zv, REBUILD_SNAPSHOT_SNAPNAME);
Expand All @@ -342,15 +395,19 @@ uzfs_zvol_destroy_snaprebuild_clone(zvol_state_t *zv,
}

/*
* Create snapshot and create clone from that snapshot
* This API is used to create internal clone for rebuild.
* It will load the clone dataset if clone already exist.
* Cloned volume created through this API can not be exposed
* to client.
*/
int
uzfs_zvol_create_snaprebuild_clone(zvol_state_t *zv,
zvol_state_t **snap_zv)
uzfs_zvol_get_or_create_internal_clone(zvol_state_t *zv,
zvol_state_t **snap_zv, zvol_state_t **clone_zv, int *error)
{
int ret = 0;
char *snapname = NULL;
char *clonename = NULL;
char *clone_subname = NULL;

ret = get_snapshot_zv(zv, REBUILD_SNAPSHOT_SNAPNAME, snap_zv);
if (ret != 0) {
Expand All @@ -366,17 +423,49 @@ uzfs_zvol_create_snaprebuild_clone(zvol_state_t *zv,
strchr(zv->zv_name, '/') + 1,
REBUILD_SNAPSHOT_CLONENAME);

clone_subname = kmem_asprintf("%s_%s", strchr(zv->zv_name, '/') + 1,
REBUILD_SNAPSHOT_CLONENAME);

ret = dmu_objset_clone(clonename, snapname);
if (ret == EEXIST) {
if (ret == EEXIST)
LOG_INFO("Volume:%s already has clone for snap rebuild",
zv->zv_name);
if (error)
*error = ret;

if ((ret == EEXIST) || (ret == 0)) {
ret = uzfs_open_dataset(zv->zv_spa, clone_subname, clone_zv);
if (ret == 0) {
ret = uzfs_hold_dataset(*clone_zv);
if (ret != 0) {
LOG_ERR("Failed to hold clone: %d", ret);
uzfs_close_dataset(*clone_zv);
*clone_zv = NULL;
/* Destroy clone */
ret = dsl_destroy_head(clonename);
if (ret != 0)
LOG_ERRNO("Rebuild_clone destroy "
"failed on:%s with err:%d",
zv->zv_name, ret);
uzfs_close_dataset(*snap_zv);
destroy_snapshot_zv(zv,
REBUILD_SNAPSHOT_SNAPNAME);
*snap_zv = NULL;
}
} else {
uzfs_close_dataset(*snap_zv);
destroy_snapshot_zv(zv, REBUILD_SNAPSHOT_SNAPNAME);
*snap_zv = NULL;
LOG_INFO("Clone:%s not able to open", clone_subname);
}
} else if (ret != 0) {
uzfs_close_dataset(*snap_zv);
destroy_snapshot_zv(zv, REBUILD_SNAPSHOT_SNAPNAME);
*snap_zv = NULL;
}

strfree(snapname);
strfree(clone_subname);
strfree(clonename);
strfree(snapname);
return (ret);
}
27 changes: 20 additions & 7 deletions lib/libzpool/zrepl_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <uzfs_rebuilding.h>

#define ZVOL_THREAD_STACKSIZE (2 * 1024 * 1024)

Expand Down Expand Up @@ -300,7 +301,9 @@ uzfs_zinfo_destroy(const char *name, spa_t *spa)
zvol_info_t *zinfo = NULL;
zvol_info_t *zt = NULL;
int namelen = ((name) ? strlen(name) : 0);
zvol_state_t *zv;
zvol_state_t *clone_zv = NULL;
zvol_state_t *snap_zv = NULL;
zvol_state_t *main_zv;
int destroyed = 0;

mutex_enter(&zvol_list_mutex);
Expand All @@ -309,14 +312,18 @@ uzfs_zinfo_destroy(const char *name, spa_t *spa)
if (name == NULL) {
SLIST_FOREACH_SAFE(zinfo, &zvol_list, zinfo_next, zt) {
if (strcmp(spa_name(spa),
spa_name(zinfo->zv->zv_spa)) == 0) {
spa_name(zinfo->main_zv->zv_spa)) == 0) {
SLIST_REMOVE(&zvol_list, zinfo, zvol_info_s,
zinfo_next);

mutex_exit(&zvol_list_mutex);
zv = zinfo->zv;
main_zv = zinfo->main_zv;
clone_zv = zinfo->clone_zv;
snap_zv = zinfo->snap_zv;
uzfs_mark_offline_and_free_zinfo(zinfo);
uzfs_close_dataset(zv);
(void) uzfs_zvol_release_internal_clone(
main_zv, &snap_zv, &clone_zv);
uzfs_close_dataset(main_zv);
destroyed++;
mutex_enter(&zvol_list_mutex);
}
Expand All @@ -331,9 +338,13 @@ uzfs_zinfo_destroy(const char *name, spa_t *spa)
zinfo_next);

mutex_exit(&zvol_list_mutex);
zv = zinfo->zv;
main_zv = zinfo->main_zv;
clone_zv = zinfo->clone_zv;
snap_zv = zinfo->snap_zv;
uzfs_mark_offline_and_free_zinfo(zinfo);
uzfs_close_dataset(zv);
(void) uzfs_zvol_release_internal_clone(
main_zv, &snap_zv, &clone_zv);
uzfs_close_dataset(main_zv);
destroyed++;
goto end;
}
Expand All @@ -354,6 +365,8 @@ uzfs_zinfo_init(void *zv, const char *ds_name, nvlist_t *create_props)
zinfo = kmem_zalloc(sizeof (zvol_info_t), KM_SLEEP);
bzero(zinfo, sizeof (zvol_info_t));
ASSERT(zinfo != NULL);
ASSERT(zinfo->clone_zv == NULL);
ASSERT(zinfo->snap_zv == NULL);

zinfo->uzfs_zvol_taskq = taskq_create("replica", boot_ncpus,
defclsyspri, boot_ncpus, INT_MAX,
Expand All @@ -364,7 +377,7 @@ uzfs_zinfo_init(void *zv, const char *ds_name, nvlist_t *create_props)
uzfs_zinfo_init_mutex(zinfo);

strlcpy(zinfo->name, ds_name, MAXNAMELEN);
zinfo->zv = zv;
zinfo->main_zv = zv;
zinfo->state = ZVOL_INFO_STATE_ONLINE;
/* iSCSI target will overwrite this value during handshake */
zinfo->update_ionum_interval = 6000;
Expand Down
Loading

0 comments on commit fa100c7

Please sign in to comment.