mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
ap_tools/ap-check: implement dynamic config during live modify
mdevctl introduces a new event type 'live' with action 'modify', indicating that the specified configuration changes should be made dynamically if possible. Use this as a trigger to perform dynamic configuration changes to the specified vfio-ap device if it is active. Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com> Reviewed-by: Anthony Krowiak <akrowiak@linux.ibm.com> Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f7425a08d1
commit
9d199e06cb
@@ -41,7 +41,8 @@ static const struct mdevctl_action mdevctl_action_table[NUM_MDEVCTL_ACTIONS] = {
|
||||
static const struct mdevctl_event mdevctl_event_table[NUM_MDEVCTL_EVENTS] = {
|
||||
{MDEVCTL_EVENT_PRE, "pre"},
|
||||
{MDEVCTL_EVENT_POST, "post"},
|
||||
{MDEVCTL_EVENT_GET, "get"}
|
||||
{MDEVCTL_EVENT_GET, "get"},
|
||||
{MDEVCTL_EVENT_LIVE, "live"}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -617,6 +618,73 @@ static int ap_check_active(struct ap_check_anchor *anc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ap_do_dynamic_config(struct ap_check_anchor *anc)
|
||||
{
|
||||
char *adapters, *domains, *controls, *path, *attr;
|
||||
int asize, dsize, csize, size;
|
||||
int rc = 0;
|
||||
FILE *f;
|
||||
|
||||
adapters = vfio_ap_device_get_adapter_mask(anc->dev, &asize);
|
||||
domains = vfio_ap_device_get_domain_mask(anc->dev, &dsize);
|
||||
controls = vfio_ap_device_get_control_mask(anc->dev, &csize);
|
||||
|
||||
if (!adapters || !domains || !controls) {
|
||||
fprintf(stderr, "Failed to read device config\n");
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The 'ap_config' command takes a comma-delimited list of the 3 masks
|
||||
* combined. Each mask size includes a terminating character, two of
|
||||
* which will be replaced by commas and the final replaced by a
|
||||
* newline, which ap_config seems to require at the end of the input.
|
||||
* Add one to ensure room for a null termination.
|
||||
*/
|
||||
size = asize + dsize + csize + 1;
|
||||
attr = util_zalloc(size);
|
||||
|
||||
/* Use the 3 masks to generate a 'ap_config' command */
|
||||
rc = snprintf(attr, size, "%s,%s,%s\n", adapters, domains, controls);
|
||||
|
||||
if (rc < size - 1) {
|
||||
fprintf(stderr, "Error creating ap_config command\n");
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Apply the new configuration to the active device */
|
||||
path = path_get_vfio_ap_attr(anc->uuid, "ap_config");
|
||||
f = fopen(path, "w");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Error opening ap_config\n");
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
rc = fputs(attr, f);
|
||||
fclose(f);
|
||||
|
||||
if (rc == EOF)
|
||||
fprintf(stderr, "Error writing to ap_config\n");
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
if (!adapters)
|
||||
free(adapters);
|
||||
if (!domains)
|
||||
free(domains);
|
||||
if (!controls)
|
||||
free(controls);
|
||||
if (!path)
|
||||
free(path);
|
||||
if (!attr)
|
||||
free(attr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if defining the specified device is a valid operation.
|
||||
* mdevctl can reach us for a DEFINE under the following circumstances:
|
||||
@@ -668,6 +736,50 @@ static int ap_check_handle_modify(struct ap_check_anchor *anc)
|
||||
return ap_check_changes(anc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if modifying the active device is a valid operation.
|
||||
* This is similar to STARTing a device, in that the requested modifications
|
||||
* cannot conflict with the active configuration. LIVE MODIFY can only be
|
||||
* handled if the ap_config attribute is available in the vfio-ap driver.
|
||||
*/
|
||||
static int ap_check_handle_live_modify(struct ap_check_anchor *anc)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ap_get_lock_callout();
|
||||
if (rc) {
|
||||
fprintf(stderr, "Failed to acquire configuration lock %d\n",
|
||||
rc);
|
||||
return -1;
|
||||
}
|
||||
anc->cleanup_lock = true;
|
||||
|
||||
if (vfio_ap_read_device_config(NULL, anc->dev) != 0) {
|
||||
fprintf(stderr, "Failed to read device config\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(anc->dev->type, anc->type) != 0) {
|
||||
fprintf(stderr, "Invalid mdev_type: %s\n", anc->dev->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!vfio_ap_need_dynamic_config(anc->dev)) {
|
||||
fprintf(stderr, "vfio-ap module does not support ap_config for live modification");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if the new configuration would cause conflicts */
|
||||
rc = ap_check_active(anc);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Attempt to perform the dynamic configuration */
|
||||
rc = ap_do_dynamic_config(anc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if starting the specified device is a valid operation.
|
||||
* mdevctl can reach us for a START under the following circumstances:
|
||||
@@ -950,6 +1062,16 @@ static int ap_check_handle_action(struct ap_check_anchor *anc)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MDEVCTL_EVENT_LIVE:
|
||||
switch (anc->action) {
|
||||
case MDEVCTL_ACTION_MODIFY:
|
||||
rc = ap_check_handle_live_modify(anc);
|
||||
break;
|
||||
default:
|
||||
/* Ignore some actions including unknown ones */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Ignore any unknown events */
|
||||
break;
|
||||
|
||||
@@ -38,6 +38,7 @@ enum mdevctl_event_id {
|
||||
MDEVCTL_EVENT_PRE = 0,
|
||||
MDEVCTL_EVENT_POST,
|
||||
MDEVCTL_EVENT_GET,
|
||||
MDEVCTL_EVENT_LIVE,
|
||||
MDEVCTL_EVENT_UNKNOWN,
|
||||
};
|
||||
#define NUM_MDEVCTL_EVENTS MDEVCTL_EVENT_UNKNOWN
|
||||
|
||||
Reference in New Issue
Block a user