diff --git a/configfs.c b/configfs.c index 222fae40..5476da17 100644 --- a/configfs.c +++ b/configfs.c @@ -60,18 +60,23 @@ int tcmu_get_attribute(struct tcmu_device *dev, const char *name) return tcmu_get_cfgfs_int(path); } -int tcmu_set_control(struct tcmu_device *dev, const char *key, unsigned long val) -{ - char path[PATH_MAX]; - char buf[CFGFS_BUF_SIZE]; - - snprintf(path, sizeof(path), CFGFS_CORE"/%s/%s/control", - dev->tcm_hba_name, dev->tcm_dev_name); - snprintf(buf, sizeof(buf), "%s=%lu", key, val); - - return tcmu_set_cfgfs_str(path, buf, strlen(buf) + 1); +#define tcmu_set_cfgfs_ctrl(type_name, type, type_frmt) \ +int tcmu_set_cfgfs_ctrl_##type_name(struct tcmu_device *dev, \ + const char *key, type val) \ +{ \ + char path[PATH_MAX]; \ + char buf[CFGFS_BUF_SIZE]; \ + \ + snprintf(path, sizeof(path), CFGFS_CORE"/%s/%s/control", \ + dev->tcm_hba_name, dev->tcm_dev_name); \ + snprintf(buf, sizeof(buf), "%s="type_frmt, key, val); \ + \ + return tcmu_set_cfgfs_str(path, buf, strlen(buf) + 1); \ } +tcmu_set_cfgfs_ctrl(ull, unsigned long long, "%llu"); +tcmu_set_cfgfs_ctrl(str, const char *, "%s"); + static bool tcmu_cfgfs_mod_param_is_supported(const char *name) { char path[PATH_MAX]; @@ -211,7 +216,7 @@ int tcmu_set_dev_size(struct tcmu_device *dev) dev_size = tcmu_get_dev_num_lbas(dev) * tcmu_get_dev_block_size(dev); - return tcmu_set_control(dev, "dev_size", dev_size); + return tcmu_set_cfgfs_ctrl_ull(dev, "dev_size", dev_size); } long long tcmu_get_dev_size(struct tcmu_device *dev) diff --git a/file_optical.c b/file_optical.c index 505b11a6..bad751de 100644 --- a/file_optical.c +++ b/file_optical.c @@ -1559,6 +1559,7 @@ static struct tcmur_handler fbo_handler = { .subtype = "fbo", .handle_cmd = fbo_handle_cmd, .nr_threads = 1, + .medium_change_supp = 1, }; /* Entry point must be named "handler_init". */ diff --git a/libtcmu.c b/libtcmu.c index 084a8f53..f6a80a96 100644 --- a/libtcmu.c +++ b/libtcmu.c @@ -141,6 +141,22 @@ lookup_dev_by_name(struct tcmulib_context *ctx, char *dev_name, int *index) return NULL; } +struct tcmu_device * +tcmulib_lookup_dev_by_tcmu_name(struct tcmulib_context *ctx, char *tcmu_name) +{ + struct tcmu_device **dev_ptr; + struct tcmu_device *dev; + + darray_foreach(dev_ptr, ctx->devices) { + dev = *dev_ptr; + + if (!strcmp(dev->tcm_dev_name, tcmu_name)) + return dev; + } + + return NULL; +} + static int reconfig_device(struct tcmulib_context *ctx, char *dev_name, struct genl_info *info) { @@ -1008,11 +1024,15 @@ struct tcmulib_cmd *tcmulib_get_next_command(struct tcmu_device *dev) return NULL; } -static int tcmu_sts_to_scsi(int tcmu_sts, uint8_t *sense) +static int tcmu_sts_to_scsi(struct tcmu_device *dev, int tcmu_sts, + uint8_t *sense, uint8_t *cdb) { - switch (tcmu_sts) { - case TCMU_STS_OK: + if (tcmu_sts == TCMU_STS_OK) return SAM_STAT_GOOD; + + tcmu_dev_dbg(dev, "Completing 0x%x with status %d\n", cdb[0], tcmu_sts); + + switch (tcmu_sts) { case TCMU_STS_NO_RESOURCE: return SAM_STAT_TASK_SET_FULL; /* @@ -1023,6 +1043,7 @@ static int tcmu_sts_to_scsi(int tcmu_sts, uint8_t *sense) case TCMU_STS_BUSY: return SAM_STAT_BUSY; case TCMU_STS_PASSTHROUGH_ERR: + case TCMU_STS_UNIT_ATTENTION: break; /* Check Conditions below */ case TCMU_STS_RANGE: @@ -1073,10 +1094,6 @@ static int tcmu_sts_to_scsi(int tcmu_sts, uint8_t *sense) /* Invalid copy target device type */ tcmu_set_sense_data(sense, COPY_ABORTED, 0x0D03); break; - case TCMU_STS_CAPACITY_CHANGED: - /* Device capacity has changed */ - tcmu_set_sense_data(sense, UNIT_ATTENTION, 0x2A09); - break; case TCMU_STS_TRANSITION: /* ALUA state transition */ tcmu_set_sense_data(sense, NOT_READY, 0x040A); @@ -1145,7 +1162,8 @@ void tcmulib_command_complete( ent->hdr.cmd_id = cmd->cmd_id; } - ent->rsp.scsi_status = tcmu_sts_to_scsi(result, cmd->sense_buf); + ent->rsp.scsi_status = tcmu_sts_to_scsi(dev, result, cmd->sense_buf, + cmd->cdb); if (ent->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) { memcpy(ent->rsp.sense_buffer, cmd->sense_buf, TCMU_SENSE_BUFFERSIZE); diff --git a/libtcmu.h b/libtcmu.h index f49de5ff..0598d01c 100644 --- a/libtcmu.h +++ b/libtcmu.h @@ -124,6 +124,13 @@ void tcmulib_processing_complete(struct tcmu_device *dev); /* Clean up loose ends when exiting */ void tcmulib_close(struct tcmulib_context *ctx); +/* + * Get a tcmu_device by its tcmu name. tcmu_name is the string found in: + * /sys/kernel/config/target/core/user_$N/$tcmu_name + */ +struct tcmu_device *tcmulib_lookup_dev_by_tcmu_name(struct tcmulib_context *ctx, + char *tcmu_name); + #ifdef __cplusplus } #endif diff --git a/libtcmu_common.h b/libtcmu_common.h index 1dfffe7e..c70e2cb1 100644 --- a/libtcmu_common.h +++ b/libtcmu_common.h @@ -33,6 +33,8 @@ enum { TCMU_STS_NO_RESOURCE, /* handler has setup sense. */ TCMU_STS_PASSTHROUGH_ERR, + /* UA code has setup the sense */ + TCMU_STS_UNIT_ATTENTION, TCMU_STS_BUSY, TCMU_STS_WR_ERR, TCMU_STS_RD_ERR, @@ -46,7 +48,6 @@ enum { TCMU_STS_HW_ERR, TCMU_STS_RANGE, TCMU_STS_FRMT_IN_PROGRESS, - TCMU_STS_CAPACITY_CHANGED, TCMU_STS_NOTSUPP_SAVE_PARAMS, TCMU_STS_WR_ERR_INCOMPAT_FRMT, TCMU_STS_TRANSITION, @@ -151,13 +152,14 @@ int tcmu_set_cfgfs_str(const char *path, const char *val, int val_len); int tcmu_get_cfgfs_int(const char *path); int tcmu_set_cfgfs_ul(const char *path, unsigned long val); int tcmu_get_attribute(struct tcmu_device *dev, const char *name); +int tcmu_set_cfgfs_ctrl_str(struct tcmu_device *dev, const char *key, + const char *val); bool tcmu_cfgfs_file_is_supported(struct tcmu_device *dev, const char *name); int tcmu_exec_cfgfs_dev_action(struct tcmu_device *dev, const char *name, unsigned long val); int tcmu_set_dev_size(struct tcmu_device *dev); long long tcmu_get_dev_size(struct tcmu_device *dev); char *tcmu_get_wwn(struct tcmu_device *dev); -int tcmu_set_control(struct tcmu_device *dev, const char *key, unsigned long val); void tcmu_reset_netlink(void); void tcmu_block_netlink(void); void tcmu_unblock_netlink(void); diff --git a/main.c b/main.c index f2e65bf1..25d5a731 100644 --- a/main.c +++ b/main.c @@ -74,46 +74,6 @@ int tcmur_register_handler(struct tcmur_handler *handler) return 0; } -static int tcmur_register_dbus_handler(struct tcmur_handler *handler) -{ - assert(handler->_is_dbus_handler == true); - return tcmur_register_handler(handler); -} - -bool tcmur_unregister_handler(struct tcmur_handler *handler) -{ - int i; - for (i = 0; i < darray_size(g_runner_handlers); i++) { - if (darray_item(g_runner_handlers, i) == handler) { - darray_remove(g_runner_handlers, i); - return true; - } - } - return false; -} - -static void free_dbus_handler(struct tcmur_handler *handler) -{ - g_free((char*)handler->opaque); - g_free((char*)handler->subtype); - g_free((char*)handler->cfg_desc); - g_free(handler); -} - -static bool tcmur_unregister_dbus_handler(struct tcmur_handler *handler) -{ - bool ret = false; - assert(handler->_is_dbus_handler == true); - - ret = tcmur_unregister_handler(handler); - - if (ret == true) { - free_dbus_handler(handler); - } - - return ret; -} - static int is_handler(const struct dirent *dirent) { if (strncmp(dirent->d_name, "handler_", 8)) @@ -229,8 +189,62 @@ on_check_config(TCMUService1 *interface, return TRUE; } +static gboolean +on_change_medium(TCMUService1 *interface, + GDBusMethodInvocation *invocation, + gchar *name, + guint64 size, + gchar *cfgstring, + gpointer user_data) +{ + struct tcmulib_context *ctx = user_data; + struct tcmur_handler *rhandler; + struct tcmu_device *dev = NULL; + char *reason = NULL; + int ret = 0; + + dev = tcmulib_lookup_dev_by_tcmu_name(ctx, name); + if (!dev) { + ret = ENODEV; + reason = "Device not found."; + goto exit; + } + + rhandler = tcmu_get_runner_handler(dev); + if (!rhandler->medium_change_supp) { + ret = EOPNOTSUPP; + reason = "Handler does not support medium changes."; + goto exit; + } + + tcmu_block_device(dev); + tcmu_flush_device(dev); + + tcmu_set_cfgfs_ctrl_str(dev, "dev_config", cfgstring); + tcmu_update_num_lbas(dev, size); + tcmu_set_dev_size(dev); + + ret = tcmu_reopen_dev(dev, false, 0); + if (ret == 0) { + reason = "success"; + } else { + reason = strerror(ret); + } + + tcmu_dev_set_pending_ua(dev, TCMUR_UA_DEV_MEDIUM_CHANGED); + tcmu_unblock_device(dev); + +exit: + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", ret, reason)); + + return TRUE; +} + static void -dbus_export_handler(struct tcmur_handler *handler, GCallback check_config) +dbus_export_handler(struct tcmulib_context *tcmulib_context, + struct tcmur_handler *handler, GCallback check_config, + GCallback change_medium) { GDBusObjectSkeleton *object; char obj_name[128]; @@ -245,204 +259,31 @@ dbus_export_handler(struct tcmur_handler *handler, GCallback check_config) "handle-check-config", check_config, handler); /* user_data */ + g_signal_connect(interface, + "handle-change-medium", + change_medium, + tcmulib_context); tcmuservice1_set_config_desc(interface, handler->cfg_desc); g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); g_object_unref(object); } -static bool -dbus_unexport_handler(struct tcmur_handler *handler) -{ - char obj_name[128]; - - snprintf(obj_name, sizeof(obj_name), "/org/kernel/TCMUService1/%s", - handler->subtype); - return g_dbus_object_manager_server_unexport(manager, obj_name) == TRUE; -} - -struct dbus_info { - guint watcher_id; - /* The RegisterHandler invocation on - * org.kernel.TCMUService1.HandlerManager1 interface. */ - GDBusMethodInvocation *register_invocation; - /* Connection to the handler's bus_name. */ - GDBusConnection *connection; -}; - -static int dbus_handler_open(struct tcmu_device *dev, bool reopen) -{ - return -1; -} - -static void dbus_handler_close(struct tcmu_device *dev) -{ - /* nop */ -} - -static int dbus_handler_handle_cmd(struct tcmu_device *dev, - struct tcmulib_cmd *cmd) -{ - abort(); -} - -static gboolean -on_dbus_check_config(TCMUService1 *interface, - GDBusMethodInvocation *invocation, - gchar *cfgstring, - gpointer user_data) -{ - char *bus_name, *obj_name; - struct tcmur_handler *handler = user_data; - GDBusConnection *connection; - GError *error = NULL; - GVariant *result; - - bus_name = g_strdup_printf("org.kernel.TCMUService1.HandlerManager1.%s", - handler->subtype); - obj_name = g_strdup_printf("/org/kernel/TCMUService1/HandlerManager1/%s", - handler->subtype); - connection = g_dbus_method_invocation_get_connection(invocation); - result = g_dbus_connection_call_sync(connection, - bus_name, - obj_name, - "org.kernel.TCMUService1", - "CheckConfig", - g_variant_new("(s)", cfgstring), - NULL, G_DBUS_CALL_FLAGS_NONE, -1, - NULL, &error); - if (result) - g_dbus_method_invocation_return_value(invocation, result); - else - g_dbus_method_invocation_return_value(invocation, - g_variant_new("(bs)", FALSE, error->message)); - g_free(bus_name); - g_free(obj_name); - return TRUE; -} - -static void -on_handler_appeared(GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - struct tcmur_handler *handler = user_data; - struct dbus_info *info = handler->opaque; - - if (info->register_invocation) { - info->connection = connection; - tcmur_register_dbus_handler(handler); - dbus_export_handler(handler, G_CALLBACK(on_dbus_check_config)); - g_dbus_method_invocation_return_value(info->register_invocation, - g_variant_new("(bs)", TRUE, "succeeded")); - info->register_invocation = NULL; - } -} - -static void -on_handler_vanished(GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - struct tcmur_handler *handler = user_data; - struct dbus_info *info = handler->opaque; - - if (info->register_invocation) { - char *reason; - reason = g_strdup_printf("Cannot find handler bus name: " - "org.kernel.TCMUService1.HandlerManager1.%s", - handler->subtype); - g_dbus_method_invocation_return_value(info->register_invocation, - g_variant_new("(bs)", FALSE, reason)); - g_free(reason); - } - dbus_unexport_handler(handler); - g_bus_unwatch_name(info->watcher_id); - tcmur_unregister_dbus_handler(handler); -} - -static gboolean -on_register_handler(TCMUService1HandlerManager1 *interface, - GDBusMethodInvocation *invocation, - gchar *subtype, - gchar *cfg_desc, - gpointer user_data) -{ - struct tcmur_handler *handler; - struct dbus_info *info; - char *bus_name; - - bus_name = g_strdup_printf("org.kernel.TCMUService1.HandlerManager1.%s", - subtype); - - handler = g_new0(struct tcmur_handler, 1); - handler->subtype = g_strdup(subtype); - handler->cfg_desc = g_strdup(cfg_desc); - handler->open = dbus_handler_open; - handler->close = dbus_handler_close; - handler->handle_cmd = dbus_handler_handle_cmd; - - info = g_new0(struct dbus_info, 1); - handler->opaque = info; - handler->_is_dbus_handler = 1; - info->register_invocation = invocation; - info->watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM, - bus_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - on_handler_appeared, - on_handler_vanished, - handler, - NULL); - if (info->watcher_id == 0) { - // probably an invalid name, roll back and report an error - free_dbus_handler(handler); - - g_dbus_method_invocation_return_value(invocation, - g_variant_new("(bs)", FALSE, - "failed to watch for DBus handler name")); - } - g_free(bus_name); - return TRUE; -} - -void dbus_handler_manager1_init(GDBusConnection *connection) -{ - GError *error = NULL; - TCMUService1HandlerManager1 *interface; - gboolean ret; - - interface = tcmuservice1_handler_manager1_skeleton_new(); - ret = g_dbus_interface_skeleton_export( - G_DBUS_INTERFACE_SKELETON(interface), - connection, - "/org/kernel/TCMUService1/HandlerManager1", - &error); - g_signal_connect(interface, - "handle-register-handler", - G_CALLBACK (on_register_handler), - NULL); - if (!ret) - tcmu_err("Handler manager export failed: %s\n", - error ? error->message : "unknown error"); - if (error) - g_error_free(error); -} - static void dbus_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) { struct tcmur_handler **handler; - tcmu_dbg("bus %s acquired\n", name); + tcmu_dbg("bus %s acquired %p\n", name, user_data); manager = g_dbus_object_manager_server_new("/org/kernel/TCMUService1"); darray_foreach(handler, g_runner_handlers) { - dbus_export_handler(*handler, G_CALLBACK(on_check_config)); + dbus_export_handler(user_data, *handler, + G_CALLBACK(on_check_config), + G_CALLBACK(on_change_medium)); } - dbus_handler_manager1_init(connection); g_dbus_object_manager_server_set_connection(manager, connection); } @@ -701,7 +542,7 @@ static int dev_resize(struct tcmu_device *dev, struct tcmulib_cfg_info *cfg) ret = tcmu_update_num_lbas(dev, cfg->data.dev_size); if (!ret) - tcmur_set_pending_ua(dev, TCMUR_UA_DEV_SIZE_CHANGED); + tcmu_dev_set_pending_ua(dev, TCMUR_UA_DEV_SIZE_CHANGED); return ret; } @@ -1121,7 +962,7 @@ int main(int argc, char **argv) dbus_bus_acquired, dbus_name_acquired, // name acquired dbus_name_lost, // name lost - NULL, // user data + tcmulib_context, // user data NULL // user date free func ); diff --git a/tcmu-handler.xml b/tcmu-handler.xml index 933d671c..4824eccf 100644 --- a/tcmu-handler.xml +++ b/tcmu-handler.xml @@ -16,6 +16,13 @@ that the configstring is valid before the device has been created. + + + + + + + diff --git a/tcmu-runner.h b/tcmu-runner.h index 47cde0d7..d09c08d9 100644 --- a/tcmu-runner.h +++ b/tcmu-runner.h @@ -59,6 +59,11 @@ struct tcmur_handler { int (*reconfig)(struct tcmu_device *dev, struct tcmulib_cfg_info *cfg); + /* + * True if handler supports medium changes via reopen calls. + */ + bool medium_change_supp; + /* Per-device added/removed callbacks */ int (*open)(struct tcmu_device *dev, bool reopen); void (*close)(struct tcmu_device *dev); @@ -125,15 +130,6 @@ struct tcmur_handler { * indicating success/failure. */ int (*get_lock_tag)(struct tcmu_device *dev, uint16_t *tag); - - /* - * internal field, don't touch this - * - * indicates to tcmu-runner whether this is an internal handler loaded - * via dlopen or an external handler registered via dbus. In the - * latter case opaque will point to a struct dbus_info. - */ - bool _is_dbus_handler; }; /* @@ -147,7 +143,6 @@ struct tcmur_handler { * APIs for tcmur only */ int tcmur_register_handler(struct tcmur_handler *handler); -bool tcmur_unregister_handler(struct tcmur_handler *handler); /* * Misc diff --git a/tcmur_cmd_handler.c b/tcmur_cmd_handler.c index a693f82e..93c0c536 100644 --- a/tcmur_cmd_handler.c +++ b/tcmur_cmd_handler.c @@ -2134,6 +2134,10 @@ int tcmur_cmd_passthrough_handler(struct tcmu_device *dev, if (!rhandler->handle_cmd) return TCMU_STS_NOT_HANDLED; + ret = tcmu_dev_handle_pending_ua(dev, cmd); + if (ret != TCMU_STS_NOT_HANDLED) + return ret; + /* * Support handlers that implement their own threading/AIO * and only use runner's main event loop. @@ -2359,52 +2363,9 @@ int tcmur_dev_update_size(struct tcmu_device *dev, unsigned long new_size) if (ret) tcmu_update_num_lbas(dev, old_size); /* Rolling back */ else - tcmur_set_pending_ua(dev, TCMUR_UA_DEV_SIZE_CHANGED); - } - - return ret; -} - -void tcmur_set_pending_ua(struct tcmu_device *dev, int ua) -{ - struct tcmur_device *rdev = tcmu_get_daemon_dev_private(dev); - - pthread_mutex_lock(&rdev->state_lock); - rdev->pending_uas |= (1 << ua); - pthread_mutex_unlock(&rdev->state_lock); -} - -/* - * TODO - coordinate with the kernel. - */ -static int handle_pending_ua(struct tcmur_device *rdev, struct tcmulib_cmd *cmd) -{ - uint8_t *cdb = cmd->cdb; - int ret = TCMU_STS_NOT_HANDLED, ua; - - switch (cdb[0]) { - case INQUIRY: - case REQUEST_SENSE: - /* The kernel will handle REPORT_LUNS */ - return TCMU_STS_NOT_HANDLED; - } - pthread_mutex_lock(&rdev->state_lock); - - if (!rdev->pending_uas) { - ret = TCMU_STS_NOT_HANDLED; - goto unlock; - } - - ua = ffs(rdev->pending_uas) - 1; - switch (ua) { - case TCMUR_UA_DEV_SIZE_CHANGED: - ret = TCMU_STS_CAPACITY_CHANGED; - break; + tcmu_dev_set_pending_ua(dev, TCMUR_UA_DEV_SIZE_CHANGED); } - rdev->pending_uas &= ~(1 << ua); -unlock: - pthread_mutex_unlock(&rdev->state_lock); return ret; } @@ -2413,7 +2374,7 @@ int tcmur_generic_handle_cmd(struct tcmu_device *dev, struct tcmulib_cmd *cmd) struct tcmur_device *rdev = tcmu_get_daemon_dev_private(dev); int ret; - ret = handle_pending_ua(rdev, cmd); + ret = tcmu_dev_handle_pending_ua(dev, cmd); if (ret != TCMU_STS_NOT_HANDLED) return ret; diff --git a/tcmur_device.c b/tcmur_device.c index efbbc755..9f4e9aa4 100644 --- a/tcmur_device.c +++ b/tcmur_device.c @@ -21,6 +21,7 @@ #include "tcmur_device.h" #include "tcmur_cmd_handler.h" #include "target.h" +#include "scsi/scsi.h" bool tcmu_dev_in_recovery(struct tcmu_device *dev) { @@ -387,3 +388,56 @@ int tcmu_acquire_dev_lock(struct tcmu_device *dev, bool is_sync, return ret; } + +void tcmu_dev_set_pending_ua(struct tcmu_device *dev, int ua) +{ + struct tcmur_device *rdev = tcmu_get_daemon_dev_private(dev); + + pthread_mutex_lock(&rdev->state_lock); + rdev->pending_uas |= (1 << ua); + pthread_mutex_unlock(&rdev->state_lock); +} + +/* + * TODO - coordinate with the kernel. + */ +int tcmu_dev_handle_pending_ua(struct tcmu_device *dev, struct tcmulib_cmd *cmd) +{ + struct tcmur_device *rdev = tcmu_get_daemon_dev_private(dev); + uint8_t *cdb = cmd->cdb; + int ret = TCMU_STS_NOT_HANDLED, ua; + + switch (cdb[0]) { + case INQUIRY: + case REQUEST_SENSE: + /* The kernel will handle REPORT_LUNS */ + return TCMU_STS_NOT_HANDLED; + } + pthread_mutex_lock(&rdev->state_lock); + + if (!rdev->pending_uas) { + ret = TCMU_STS_NOT_HANDLED; + goto unlock; + } + + ua = ffs(rdev->pending_uas) - 1; + switch (ua) { + case TCMUR_UA_DEV_SIZE_CHANGED: + /* Device capacity has changed */ + tcmu_set_sense_data(cmd->sense_buf, UNIT_ATTENTION, 0x2A09); + break; + case TCMUR_UA_DEV_MEDIUM_CHANGED: + /* medium changed */ + tcmu_set_sense_data(cmd->sense_buf, UNIT_ATTENTION, 0x2800); + break; + default: + tcmu_dev_err(dev, "Unhandled UA %d\n", ua); + goto unlock; + } + ret = TCMU_STS_UNIT_ATTENTION; + rdev->pending_uas &= ~(1 << ua); + +unlock: + pthread_mutex_unlock(&rdev->state_lock); + return ret; +} diff --git a/tcmur_device.h b/tcmur_device.h index 128a8ba8..f72af914 100644 --- a/tcmur_device.h +++ b/tcmur_device.h @@ -22,6 +22,7 @@ #define TCMUR_DEV_FLAG_STOPPED (1 << 4) #define TCMUR_UA_DEV_SIZE_CHANGED 0 +#define TCMUR_UA_DEV_MEDIUM_CHANGED 1 enum { TMCUR_DEV_FAILOVER_ALL_ACTIVE, @@ -84,4 +85,7 @@ int tcmu_acquire_dev_lock(struct tcmu_device *dev, bool is_sync, uint16_t tag); void tcmu_release_dev_lock(struct tcmu_device *dev); int tcmu_get_lock_tag(struct tcmu_device *dev, uint16_t *tag); +void tcmu_dev_set_pending_ua(struct tcmu_device *dev, int ua); +int tcmu_dev_handle_pending_ua(struct tcmu_device *dev, struct tcmulib_cmd *cmd) +; #endif