commit 4b080ac4b0124a911e3785ce3ac77001390d1a23 Author: Hannes Reinecke Date: Fri Sep 26 16:07:13 2008 +0200 multipath: Implement 'resize map' cli command To properly support device resize we'll have to notify multipath about the size changes, too. References: FATE#302007 Signed-off-by: Hannes Reinecke diff --git a/libmultipath/configure.c b/libmultipath/configure.c index 43324c6..8444ef2 100644 --- a/libmultipath/configure.c +++ b/libmultipath/configure.c @@ -348,7 +348,16 @@ domap (struct multipath * mpp) case ACT_RELOAD: r = (dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL) - && dm_simplecmd(DM_DEVICE_RESUME, mpp->alias)); + && dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, 1)); + break; + + case ACT_RESIZE: + r = dm_addmap_reload(mpp->alias, mpp->params, mpp->size, NULL); + if (!r) + r = dm_addmap_reload_ro(mpp->alias, mpp->params, + mpp->size, NULL); + if (r) + r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, 0); break; case ACT_RENAME: diff --git a/libmultipath/configure.h b/libmultipath/configure.h index 75d5057..25891ba 100644 --- a/libmultipath/configure.h +++ b/libmultipath/configure.h @@ -7,6 +7,7 @@ #define ACT_SWITCHPG_STR "switchpg" #define ACT_RENAME_STR "rename" #define ACT_CREATE_STR "create" +#define ACT_RESIZE_STR "resize" enum actions { ACT_UNDEF, @@ -15,7 +16,8 @@ enum actions { ACT_RELOAD, ACT_SWITCHPG, ACT_RENAME, - ACT_CREATE + ACT_CREATE, + ACT_RESIZE, }; #define FLUSH_ONE 1 diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c index 70e10c2..92afae7 100644 --- a/libmultipath/devmapper.c +++ b/libmultipath/devmapper.c @@ -150,7 +150,7 @@ dm_prereq (void) } extern int -dm_simplecmd (int task, const char *name) { +dm_simplecmd (int task, const char *name, int no_flush) { int r = 0; struct dm_task *dmt; @@ -163,7 +163,8 @@ dm_simplecmd (int task, const char *name) { dm_task_no_open_count(dmt); dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ #ifdef LIBDM_API_FLUSH - dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + if (no_flush) + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ #endif r = dm_task_run (dmt); @@ -536,7 +537,7 @@ dm_flush_map (const char * mapname) return 1; } - r = dm_simplecmd(DM_DEVICE_REMOVE, mapname); + r = dm_simplecmd(DM_DEVICE_REMOVE, mapname, 0); if (r) { condlog(4, "multipath map %s removed", mapname); @@ -933,7 +934,7 @@ dm_remove_partmaps (const char * mapname) */ condlog(4, "partition map %s removed", names->name); - dm_simplecmd(DM_DEVICE_REMOVE, names->name); + dm_simplecmd(DM_DEVICE_REMOVE, names->name, 0); } next = names->next; diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h index a340c00..b262efa 100644 --- a/libmultipath/devmapper.h +++ b/libmultipath/devmapper.h @@ -3,7 +3,7 @@ void dm_init(void); int dm_prereq (void); -int dm_simplecmd (int, const char *); +int dm_simplecmd (int, const char *, int); int dm_addmap_create (const char *, const char *, unsigned long long size, const char *uuid); int dm_addmap_create_ro (const char *, const char *, diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h index e7fa3e7..2cd762f 100644 --- a/libmultipath/sysfs.h +++ b/libmultipath/sysfs.h @@ -21,5 +21,6 @@ struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device void sysfs_device_put(struct sysfs_device *dev); char *sysfs_attr_get_value(const char *devpath, const char *attr_name); int sysfs_resolve_link(char *path, size_t size); +int sysfs_get_size (struct sysfs_device * dev, unsigned long long * size); #endif diff --git a/multipathd/cli.c b/multipathd/cli.c index 7eaac73..f5b9797 100644 --- a/multipathd/cli.c +++ b/multipathd/cli.c @@ -155,6 +155,7 @@ load_keys (void) r += add_key(keys, "resume", RESUME, 0); r += add_key(keys, "reinstate", REINSTATE, 0); r += add_key(keys, "fail", FAIL, 0); + r += add_key(keys, "resize", RESIZE, 0); r += add_key(keys, "paths", PATHS, 0); r += add_key(keys, "maps", MAPS, 0); r += add_key(keys, "multipaths", MAPS, 0); diff --git a/multipathd/cli.h b/multipathd/cli.h index 8c83eab..d4a038c 100644 --- a/multipathd/cli.h +++ b/multipathd/cli.h @@ -7,6 +7,7 @@ enum { __RESUME, __REINSTATE, __FAIL, + __RESIZE, __PATHS, __MAPS, __PATH, @@ -30,6 +31,7 @@ enum { #define RESUME (1 << __RESUME) #define REINSTATE (1 << __REINSTATE) #define FAIL (1 << __FAIL) +#define RESIZE (1 << __RESIZE) #define PATHS (1 << __PATHS) #define MAPS (1 << __MAPS) #define PATH (1 << __PATH) diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c index c84805a..38130f5 100644 --- a/multipathd/cli_handlers.c +++ b/multipathd/cli_handlers.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "main.h" #include "cli.h" @@ -362,12 +363,139 @@ cli_del_map (void * v, char ** reply, int * len, void * data) } int +reload_paths(struct multipath *mpp, struct vectors * vecs) +{ + struct pathgroup *pgp; + struct path *pp; + int i, j, err = 1; + char *dev; + vector path_names; + + path_names = vector_alloc(); + if (!path_names){ + condlog(0, "%s: unable to allcoate space for pathnames vector", + mpp->alias); + return 1; + } + vector_foreach_slot(mpp->pg, pgp, i) { + vector_foreach_slot(pgp->paths, pp, j) { + + dev = strdup(pp->dev); + if (!dev) { + condlog(0, "%s: unable to allocate path name", + mpp->alias); + goto out; + } + if (!vector_alloc_slot(path_names)){ + condlog(0, "%s: unable to allocate path name slot", + mpp->alias); + free(dev); + goto out; + } + vector_set_slot(path_names, dev); + } + } + vector_foreach_slot(path_names, dev, i) { + err = ev_remove_path(dev, vecs); + if (err) { + condlog(0, "%s: couldn't remove path '%s' : %s", + mpp->alias, dev, strerror(errno)); + goto out; + } + err = ev_add_path(dev, vecs); + if (err) + condlog(0, "%s: couldn't add path '%s' : %s", + mpp->alias, dev, strerror(errno)); + } +out: + vector_foreach_slot(path_names, dev, i) + free(dev); + vector_free(path_names); + return err; +} + +int resize_map(struct multipath *mpp, unsigned long long size, + struct vectors * vecs) +{ + mpp->size = size; + update_mpp_paths(mpp, vecs->pathvec); + setup_map(mpp); + mpp->action = ACT_RESIZE; + if (domap(mpp) <= 0) { + condlog(0, "%s: failed to resize map : %s", mpp->alias, + strerror(errno)); + return 1; + } + return 0; +} + +int +cli_resize(void *v, char **reply, int *len, void *data) +{ + struct vectors * vecs = (struct vectors *)data; + char * mapname = get_keyparam(v, MAP); + struct multipath *mpp; + int minor; + unsigned long long size; + struct pathgroup *pgp; + struct path *pp; + + condlog(2, "%s: resize map (operator)", mapname); + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); + else + mpp = find_mp_by_alias(vecs->mpvec, mapname); + + if (!mpp) { + condlog(0, "%s: invalid map name. cannot resize", mapname); + return 1; + } + + pgp = VECTOR_SLOT(mpp->pg, 0); + pp = VECTOR_SLOT(pgp->paths, 0); + if (sysfs_get_size(pp->sysdev, &size)) { + condlog(0, "%s: couldn't get size for sysfs. cannot resize", + mapname); + return 1; + } + if (size == mpp->size) { + condlog(0, "%s: map is still the same size (%llu)", mapname, + mpp->size); + return 0; + } + condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size, + size); + if (size > mpp->size) { + if (reload_paths(mpp, vecs) != 0) { + condlog(0, "%s: failed to reload paths", mapname); + return 1; + } + if (resize_map(mpp, size, vecs) != 0) + return 1; + } + else { + if (resize_map(mpp, size, vecs) != 0) + return 1; + if (reload_paths(mpp, vecs) != 0) { + condlog(0, "%s: failed to reload paths", mapname); + return 1; + } + } + dm_lib_release(); + setup_multipath(vecs, mpp); + sync_map_state(mpp); + + return 0; +} + +int cli_switch_group(void * v, char ** reply, int * len, void * data) { char * mapname = get_keyparam(v, MAP); int groupnum = atoi(get_keyparam(v, GROUP)); - - condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum); + + condlog(2, "%s: switch to path group #%i (operator)", + mapname, groupnum); return dm_switchgroup(mapname, groupnum); } @@ -376,7 +504,7 @@ int cli_reconfigure(void * v, char ** reply, int * len, void * data) { struct vectors * vecs = (struct vectors *)data; - + condlog(2, "reconfigure (operator)"); return reconfigure(vecs); @@ -387,18 +515,17 @@ cli_suspend(void * v, char ** reply, int * len, void * data) { struct vectors * vecs = (struct vectors *)data; char * param = get_keyparam(v, MAP); - int r = dm_simplecmd(DM_DEVICE_SUSPEND, param); + int r = dm_simplecmd(DM_DEVICE_SUSPEND, param, 1); + struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); condlog(2, "%s: suspend (operator)", param); if (!r) /* error */ return 1; - - struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); if (!mpp) return 1; - + dm_get_info(param, &mpp->dmi); return 0; } @@ -408,18 +535,17 @@ cli_resume(void * v, char ** reply, int * len, void * data) { struct vectors * vecs = (struct vectors *)data; char * param = get_keyparam(v, MAP); - int r = dm_simplecmd(DM_DEVICE_RESUME, param); + int r = dm_simplecmd(DM_DEVICE_RESUME, param, 1); + struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); condlog(2, "%s: resume (operator)", param); if (!r) /* error */ return 1; - - struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); if (!mpp) return 1; - + dm_get_info(param, &mpp->dmi); return 0; } @@ -430,7 +556,7 @@ cli_reinstate(void * v, char ** reply, int * len, void * data) struct vectors * vecs = (struct vectors *)data; char * param = get_keyparam(v, PATH); struct path * pp; - + pp = find_path_by_dev(vecs->pathvec, param); if (!pp) @@ -453,7 +579,7 @@ cli_fail(void * v, char ** reply, int * len, void * data) char * param = get_keyparam(v, PATH); struct path * pp; int r; - + pp = find_path_by_dev(vecs->pathvec, param); if (!pp) @@ -477,67 +603,67 @@ cli_fail(void * v, char ** reply, int * len, void * data) int show_blacklist (char ** r, int * len) { - char *c = NULL; - char *reply = NULL; - unsigned int maxlen = INITIAL_REPLY_LEN; - int again = 1; + char *c = NULL; + char *reply = NULL; + unsigned int maxlen = INITIAL_REPLY_LEN; + int again = 1; - while (again) { + while (again) { reply = MALLOC(maxlen); if (!reply) return 1; - c = reply; - c += snprint_blacklist_report(c, maxlen); - again = ((c - reply) == maxlen); - if (again) { + c = reply; + c += snprint_blacklist_report(c, maxlen); + again = ((c - reply) == maxlen); + if (again) { maxlen *= 2; FREE(reply); - continue; - } - } + continue; + } + } - *r = reply; - *len = (int)(c - reply + 1); + *r = reply; + *len = (int)(c - reply + 1); - return 0; + return 0; } int cli_list_blacklist (void * v, char ** reply, int * len, void * data) { - condlog(3, "list blacklist (operator)"); + condlog(3, "list blacklist (operator)"); - return show_blacklist(reply, len); + return show_blacklist(reply, len); } int show_devices (char ** r, int * len, struct vectors *vecs) { - char *c = NULL; - char *reply = NULL; - unsigned int maxlen = INITIAL_REPLY_LEN; - int again = 1; - - while (again) { - reply = MALLOC(maxlen); - if (!reply) - return 1; - - c = reply; - c += snprint_devices(c, maxlen, vecs); - again = ((c - reply) == maxlen); - if (again) { - maxlen *= 2; - FREE(reply); - continue; - } - } - - *r = reply; - *len = (int)(c - reply + 1); - - return 0; + char *c = NULL; + char *reply = NULL; + unsigned int maxlen = INITIAL_REPLY_LEN; + int again = 1; + + while (again) { + reply = MALLOC(maxlen); + if (!reply) + return 1; + + c = reply; + c += snprint_devices(c, maxlen, vecs); + again = ((c - reply) == maxlen); + if (again) { + maxlen *= 2; + FREE(reply); + continue; + } + } + + *r = reply; + *len = (int)(c - reply + 1); + + return 0; } int @@ -545,7 +671,7 @@ cli_list_devices (void * v, char ** reply, int * len, void * data) { struct vectors * vecs = (struct vectors *)data; - condlog(3, "list devices (operator)"); + condlog(3, "list devices (operator)"); - return show_devices(reply, len, vecs); + return show_devices(reply, len, vecs); } diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h index a688481..72ed54a 100644 --- a/multipathd/cli_handlers.h +++ b/multipathd/cli_handlers.h @@ -14,6 +14,7 @@ int cli_add_map (void * v, char ** reply, int * len, void * data); int cli_del_map (void * v, char ** reply, int * len, void * data); int cli_switch_group(void * v, char ** reply, int * len, void * data); int cli_reconfigure(void * v, char ** reply, int * len, void * data); +int cli_resize(void * v, char ** reply, int * len, void * data); int cli_suspend(void * v, char ** reply, int * len, void * data); int cli_resume(void * v, char ** reply, int * len, void * data); int cli_reinstate(void * v, char ** reply, int * len, void * data); diff --git a/multipathd/main.c b/multipathd/main.c index 4fbac3b..b1e440a 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -147,7 +147,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv) return 0; } -static void +void sync_map_state(struct multipath *mpp) { struct pathgroup *pgp; @@ -709,6 +709,7 @@ uxlsnrloop (void * ap) set_handler_callback(RECONFIGURE, cli_reconfigure); set_handler_callback(SUSPEND+MAP, cli_suspend); set_handler_callback(RESUME+MAP, cli_resume); + set_handler_callback(RESIZE+MAP, cli_resize); set_handler_callback(REINSTATE+PATH, cli_reinstate); set_handler_callback(FAIL+PATH, cli_fail); diff --git a/multipathd/main.h b/multipathd/main.h index 1a6dc55..d73cd70 100644 --- a/multipathd/main.h +++ b/multipathd/main.h @@ -9,5 +9,6 @@ int ev_add_path (char *, struct vectors *); int ev_remove_path (char *, struct vectors *); int ev_add_map (struct sysfs_device *, struct vectors *); int ev_remove_map (char *, struct vectors *); +void sync_map_state (struct multipath *); #endif /* MAIN_H */