|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 2/2] mini-os: netfront: fix suspend/resume handling
Juergen Gross, le mar. 22 sept. 2020 12:58:26 +0200, a ecrit:
> Suspend/resume handling of netfront is completely broken from the
> beginning. Commit d225f4012d69a1 ("Save/Restore Support: Add
> suspend/restore support for netfront") introduced a new structure
> netfront_dev_list referencing the real struct netfront_dev elements.
> This list is used to setup the devices when resuming again.
>
> Unfortunately the netfront_dev elements are released during suspend,
> so at resume time those references will be stale.
>
> Fix this whole mess by dropping struct netfront_dev_list again and
> link the netfront_dev elements directly into a list. When suspending
> don't free those elements.
>
> The ip-address, netmask and gateway strings can just be released when
> suspending and reread from xenstore at resume time.
>
> Fixes: d225f4012d69a1 ("Save/Restore Support: Add suspend/restore support for
> netfront")
> Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
> ---
> netfront.c | 162 ++++++++++++++++++++++-------------------------------
> 1 file changed, 67 insertions(+), 95 deletions(-)
>
> diff --git a/netfront.c b/netfront.c
> index 9057908..2075410 100644
> --- a/netfront.c
> +++ b/netfront.c
> @@ -36,6 +36,8 @@ struct net_buffer {
> };
>
> struct netfront_dev {
> + int refcount;
> +
> domid_t dom;
>
> unsigned short tx_freelist[NET_TX_RING_SIZE + 1];
> @@ -66,27 +68,19 @@ struct netfront_dev {
> void (*netif_rx)(unsigned char* data, int len, void* arg);
> void *netif_rx_arg;
>
> - struct netfront_dev_list *ldev;
> -};
> -
> -struct netfront_dev_list {
> - struct netfront_dev *dev;
> unsigned char rawmac[6];
> char *ip;
> char *mask;
> char *gw;
>
> - int refcount;
> -
> - struct netfront_dev_list *next;
> + struct netfront_dev *next;
> };
>
> -static struct netfront_dev_list *dev_list = NULL;
> +static struct netfront_dev *dev_list = NULL;
>
> void init_rx_buffers(struct netfront_dev *dev);
> -static struct netfront_dev *_init_netfront(struct netfront_dev *dev,
> - unsigned char rawmac[6], char
> **ip, char **mask, char **gw);
> -static void _shutdown_netfront(struct netfront_dev *dev);
> +static struct netfront_dev *_init_netfront(struct netfront_dev *dev);
> +static int _shutdown_netfront(struct netfront_dev *dev);
> void netfront_set_rx_handler(struct netfront_dev *dev,
> void (*thenetif_rx)(unsigned char *data, int
> len,
> void *arg),
> @@ -276,6 +270,7 @@ static void free_netfront(struct netfront_dev *dev)
> mask_evtchn(dev->evtchn);
>
> free(dev->mac);
> + free(dev->ip);
> free(dev->backend);
>
> gnttab_end_access(dev->rx_ring_ref);
> @@ -309,8 +304,7 @@ struct netfront_dev *init_netfront(char *_nodename,
> {
> char nodename[256];
> struct netfront_dev *dev;
> - struct netfront_dev_list *ldev = NULL;
> - struct netfront_dev_list *list = NULL;
> + struct netfront_dev *list;
> static int netfrontends = 0;
>
> if (!_nodename)
> @@ -321,10 +315,9 @@ struct netfront_dev *init_netfront(char *_nodename,
> }
>
> /* Check if the device is already initialized */
> - for (list = dev_list; list != NULL; list = list->next) {
> - if (strcmp(nodename, list->dev->nodename) == 0) {
> - list->refcount++;
> - dev = list->dev;
> + for (dev = dev_list; dev != NULL; dev = dev->next) {
> + if (strcmp(nodename, dev->nodename) == 0) {
> + dev->refcount++;
> if (thenetif_rx)
> netfront_set_rx_handler(dev, thenetif_rx, NULL);
> goto out;
> @@ -345,40 +338,34 @@ struct netfront_dev *init_netfront(char *_nodename,
> dev->netif_rx = thenetif_rx;
> dev->netif_rx_arg = NULL;
>
> - ldev = malloc(sizeof(struct netfront_dev_list));
> - memset(ldev, 0, sizeof(struct netfront_dev_list));
> -
> - if (_init_netfront(dev, ldev->rawmac, &(ldev->ip), &(ldev->mask),
> &(ldev->gw))) {
> - dev->ldev = ldev;
> - ldev->dev = dev;
> - ldev->refcount = 1;
> - ldev->next = NULL;
> + if (_init_netfront(dev)) {
> + dev->refcount = 1;
> + dev->next = NULL;
>
> if (!dev_list) {
> - dev_list = ldev;
> + dev_list = dev;
> } else {
> for (list = dev_list; list->next != NULL; list = list->next)
> ;
> - list->next = ldev;
> - }
> + list->next = dev;
> + }
> netfrontends++;
> } else {
> - free(ldev);
> dev = NULL;
> goto err;
> }
>
> out:
> if (rawmac) {
> - rawmac[0] = ldev->rawmac[0];
> - rawmac[1] = ldev->rawmac[1];
> - rawmac[2] = ldev->rawmac[2];
> - rawmac[3] = ldev->rawmac[3];
> - rawmac[4] = ldev->rawmac[4];
> - rawmac[5] = ldev->rawmac[5];
> + rawmac[0] = dev->rawmac[0];
> + rawmac[1] = dev->rawmac[1];
> + rawmac[2] = dev->rawmac[2];
> + rawmac[3] = dev->rawmac[3];
> + rawmac[4] = dev->rawmac[4];
> + rawmac[5] = dev->rawmac[5];
> }
> if (ip)
> - *ip = strdup(ldev->ip);
> + *ip = strdup(dev->ip);
>
> err:
> return dev;
> @@ -386,17 +373,15 @@ err:
>
> char *netfront_get_netmask(struct netfront_dev *dev)
> {
> - return dev->ldev->mask ? strdup(dev->ldev->mask) : NULL;
> + return dev->mask ? strdup(dev->mask) : NULL;
> }
>
> char *netfront_get_gateway(struct netfront_dev *dev)
> {
> - return dev->ldev->gw ? strdup(dev->ldev->gw) : NULL;
> + return dev->gw ? strdup(dev->gw) : NULL;
> }
>
> -static struct netfront_dev *_init_netfront(struct netfront_dev *dev,
> - unsigned char rawmac[6],
> - char **ip, char **mask, char **gw)
> +static struct netfront_dev *_init_netfront(struct netfront_dev *dev)
> {
> xenbus_transaction_t xbt;
> char* err = NULL;
> @@ -518,6 +503,8 @@ done:
> {
> XenbusState state;
> char path[strlen(dev->backend) + strlen("/state") + 1];
> + char *p;
> +
> snprintf(path, sizeof(path), "%s/state", dev->backend);
>
> xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
> @@ -532,26 +519,18 @@ done:
> goto error;
> }
>
> - if (ip) {
> - char *p;
> -
> - snprintf(path, sizeof(path), "%s/ip", dev->backend);
> - xenbus_read(XBT_NIL, path, ip);
> -
> - if (mask) {
> - p = strchr(*ip, ' ');
> - if (p) {
> - *p++ = '\0';
> - *mask = p;
> -
> - if (gw) {
> - p = strchr(p, ' ');
> - if (p) {
> - *p++ = '\0';
> - *gw = p;
> - }
> - }
> - }
> + snprintf(path, sizeof(path), "%s/ip", dev->backend);
> + xenbus_read(XBT_NIL, path, &dev->ip);
> +
> + p = strchr(dev->ip, ' ');
> + if (p) {
> + *p++ = '\0';
> + dev->mask = p;
> +
> + p = strchr(p, ' ');
> + if (p) {
> + *p++ = '\0';
> + dev->gw = p;
> }
> }
> }
> @@ -563,14 +542,13 @@ done:
> /* Special conversion specifier 'hh' needed for __ia64__. Without
> * this mini-os panics with 'Unaligned reference'.
> */
> - if (rawmac)
> - sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
> - &rawmac[0],
> - &rawmac[1],
> - &rawmac[2],
> - &rawmac[3],
> - &rawmac[4],
> - &rawmac[5]);
> + sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
> + &dev->rawmac[0],
> + &dev->rawmac[1],
> + &dev->rawmac[2],
> + &dev->rawmac[3],
> + &dev->rawmac[4],
> + &dev->rawmac[5]);
>
> return dev;
>
> @@ -600,38 +578,33 @@ int netfront_tap_open(char *nodename) {
>
> void shutdown_netfront(struct netfront_dev *dev)
> {
> - struct netfront_dev_list *list = NULL;
> - struct netfront_dev_list *to_del = NULL;
> + struct netfront_dev *list;
>
> /* Check this is a valid device */
> - for (list = dev_list; list != NULL; list = list->next) {
> - if (list->dev == dev)
> - break;
> - }
> + for (list = dev_list; list != NULL && list != dev; list = list->next);
>
> if (!list) {
> printk("Trying to shutdown an invalid netfront device (%p)\n", dev);
> return;
> }
>
> - list->refcount--;
> - if (list->refcount == 0) {
> - _shutdown_netfront(dev);
> + dev->refcount--;
> + if (dev->refcount == 0) {
> + if (_shutdown_netfront(dev))
> + return;
>
> - to_del = list;
> - if (to_del == dev_list) {
> - free(to_del);
> - dev_list = NULL;
> + if (dev == dev_list) {
> + dev_list = NULL;
> } else {
> - for (list = dev_list; list->next != to_del; list = list->next)
> + for (list = dev_list; list->next != dev; list = list->next)
> ;
> - list->next = to_del->next;
> - free(to_del);
> + list->next = dev->next;
> }
> + free_netfront(dev);
> }
> }
>
> -static void _shutdown_netfront(struct netfront_dev *dev)
> +static int _shutdown_netfront(struct netfront_dev *dev)
> {
> char* err = NULL, *err2;
> XenbusState state;
> @@ -692,24 +665,23 @@ close:
> err2 = xenbus_rm(XBT_NIL, nodename);
> free(err2);
>
> - if (!err)
> - free_netfront(dev);
> + return err ? -EBUSY : 0;
> }
>
> void suspend_netfront(void)
> {
> - struct netfront_dev_list *list;
> + struct netfront_dev *dev;
>
> - for (list = dev_list; list != NULL; list = list->next)
> - _shutdown_netfront(list->dev);
> + for (dev = dev_list; dev != NULL; dev = dev->next)
> + _shutdown_netfront(dev);
> }
>
> void resume_netfront(void)
> {
> - struct netfront_dev_list *list;
> + struct netfront_dev *dev;
>
> - for (list = dev_list; list != NULL; list = list->next)
> - _init_netfront(list->dev, NULL, NULL, NULL, NULL);
> + for (dev = dev_list; dev != NULL; dev = dev->next)
> + _init_netfront(dev);
> }
>
> void init_rx_buffers(struct netfront_dev *dev)
> --
> 2.26.2
>
--
Samuel
tohi.cybercable.fr (212.198.0.3) si une personne se reconnait derriere
cette adresse que ce soit un pirate ou une victime qu'il se manifeste,
cette personne pourrait bien etre un petit malin
-+- Fred in NPC : Mamaaaaan, y a le routeur qui veut me hacker -+-
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |