Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/632625/?format=api
{ "id": 632625, "url": "http://patchwork.ozlabs.org/api/patches/632625/?format=api", "web_url": "http://patchwork.ozlabs.org/project/petitboot/patch/20160609045909.17049-3-sam@mendozajonas.com/", "project": { "id": 53, "url": "http://patchwork.ozlabs.org/api/projects/53/?format=api", "name": "Petitboot development", "link_name": "petitboot", "list_id": "petitboot.lists.ozlabs.org", "list_email": "petitboot@lists.ozlabs.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20160609045909.17049-3-sam@mendozajonas.com>", "list_archive_url": null, "date": "2016-06-09T04:59:09", "name": "[3/3] discover/pxe-parser: Retrieve configs asynchronously", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "592d0664ca1589cd0ed4e9dc875286375e88a0f2", "submitter": { "id": 68013, "url": "http://patchwork.ozlabs.org/api/people/68013/?format=api", "name": "Sam Mendoza-Jonas", "email": "sam@mendozajonas.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/petitboot/patch/20160609045909.17049-3-sam@mendozajonas.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/632625/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/632625/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "petitboot@lists.ozlabs.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "petitboot@lists.ozlabs.org" ], "Received": [ "from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3rQClM3rcYz9sf9\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 9 Jun 2016 14:59:27 +1000 (AEST)", "from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3rQClM2h1szDqPX\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 9 Jun 2016 14:59:27 +1000 (AEST)", "from mendozajonas.com (mendozajonas.com [188.166.185.233])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3rQClF298DzDq5g\n\tfor <petitboot@lists.ozlabs.org>;\n\tThu, 9 Jun 2016 14:59:21 +1000 (AEST)", "from skellige.ozlabs.ibm.com (unknown [122.99.82.10])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128\n\tbits)) (Client did not present a certificate)\n\t(Authenticated sender: sam@mendozajonas.com)\n\tby mendozajonas.com (Postfix) with ESMTPSA id 75167143F73\n\tfor <petitboot@lists.ozlabs.org>;\n\tThu, 9 Jun 2016 12:59:16 +0800 (SGT)" ], "Authentication-Results": [ "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=mendozajonas.com header.i=@mendozajonas.com\n\theader.b=ippBPVjU; dkim-atps=neutral", "lists.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=mendozajonas.com header.i=@mendozajonas.com\n\theader.b=ippBPVjU; dkim-atps=neutral", "lists.ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=mendozajonas.com header.i=@mendozajonas.com\n\theader.b=ippBPVjU; dkim-atps=neutral" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=mendozajonas.com;\n\ts=mail; t=1465448356;\n\tbh=fBCavTjfZrJ1umVFiE1A1qTn3kZ9AxZ4S1+NZkV4I9s=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=ippBPVjUZbq6XJ74+sQnajBNh5u2o5iCUWjcS7oWWyeBU+RoEg/wvX7kvfvG4dfl/\n\t3y2AQylJWdtetf95jsQg4haq0B89Whk9eQGt0vX82+Q+HI7kpGcIQ2QpiS1Ke8rdn0\n\tr0URiHF+zbPWtvuGfFJnaFxvKsu4CmBYyqwrbtHs=", "From": "Samuel Mendoza-Jonas <sam@mendozajonas.com>", "To": "petitboot@lists.ozlabs.org", "Subject": "[PATCH 3/3] discover/pxe-parser: Retrieve configs asynchronously", "Date": "Thu, 9 Jun 2016 14:59:09 +1000", "Message-Id": "<20160609045909.17049-3-sam@mendozajonas.com>", "X-Mailer": "git-send-email 2.8.3", "In-Reply-To": "<20160609045909.17049-1-sam@mendozajonas.com>", "References": "<20160609045909.17049-1-sam@mendozajonas.com>", "X-BeenThere": "petitboot@lists.ozlabs.org", "X-Mailman-Version": "2.1.22", "Precedence": "list", "List-Id": "Petitboot bootloader development <petitboot.lists.ozlabs.org>", "List-Unsubscribe": "<https://lists.ozlabs.org/options/petitboot>,\n\t<mailto:petitboot-request@lists.ozlabs.org?subject=unsubscribe>", "List-Archive": "<http://lists.ozlabs.org/pipermail/petitboot/>", "List-Post": "<mailto:petitboot@lists.ozlabs.org>", "List-Help": "<mailto:petitboot-request@lists.ozlabs.org?subject=help>", "List-Subscribe": "<https://lists.ozlabs.org/listinfo/petitboot>,\n\t<mailto:petitboot-request@lists.ozlabs.org?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org", "Sender": "\"Petitboot\"\n\t<petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>" }, "content": "Depending on the configuration of the DHCP server and the network, tftp\nrequests made by the pxe parser can timeout. The pxe parser makes these\nrequests synchronously so several timeouts can block the server\ncompletely for several minutes, leaving the server unresponsive to UI\nrequests.\n\nRework the pxe parser such that it handles the result of each tftp\nrequest in a callback, which can complete after iterate_parsers() has\nreturned. A discover_context and conf_context are cloned for each\nrequest so that the callbacks can handle new boot options even after the\niterate loop has completed.\n\nSigned-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>\n---\n discover/pxe-parser.c | 171 ++++++++++++++++++++++++++++++++++++++------------\n lib/url/url.c | 2 +-\n lib/url/url.h | 1 +\n 3 files changed, 132 insertions(+), 42 deletions(-)", "diff": "diff --git a/discover/pxe-parser.c b/discover/pxe-parser.c\nindex 4812c37..9e880b2 100644\n--- a/discover/pxe-parser.c\n+++ b/discover/pxe-parser.c\n@@ -8,6 +8,7 @@\n #include <talloc/talloc.h>\n #include <url/url.h>\n #include <log/log.h>\n+#include <file/file.h>\n \n #include \"parser.h\"\n #include \"parser-conf.h\"\n@@ -197,87 +198,175 @@ static void pxe_process_pair(struct conf_context *ctx,\n \n }\n \n-static int pxe_parse(struct discover_context *dc)\n+/*\n+ * Callback for asynchronous loads from pxe_parse()\n+ * @param result Result of load_url_async()\n+ * @param data Pointer to associated conf_context\n+ */\n+static void pxe_conf_parse_cb(struct load_url_result *result, void *data)\n {\n-\tstruct pb_url *pxe_base_url, *url;\n-\tstruct pxe_parser_info *parser_info;\n-\tchar **pxe_conf_files, **filename;\n-\tstruct conf_context *conf;\n-\tbool complete_url;\n+\tstruct conf_context *conf = data;\n+\tstruct device_handler *handler;\n+\tstruct boot_status status = {0};\n+\tchar *buf = NULL;\n \tint len, rc;\n-\tchar *buf;\n \n-\t/* Expects dhcp event parameters to support network boot */\n-\tif (!dc->event)\n-\t\treturn -1;\n+\tif (!data || !result || result->status != LOAD_OK)\n+\t\treturn;\n+\n+\trc = read_file(conf, result->local, &buf, &len);\n+\tif (rc) {\n+\t\tpb_log(\"Read failed during pxe callback for %s\\n\", result->local);\n+\t\tgoto out_clean;\n+\t}\n+\n+\tconf_parse_buf(conf, buf, len);\n+\n+\t/* We may be called well after the original caller of iterate_parsers(),\n+\t * commit any new boot options ourselves */\n+\thandler = talloc_parent(conf);\n+\tdevice_handler_discover_context_commit(handler, conf->dc);\n \n-\tconf = talloc_zero(dc, struct conf_context);\n+\tstatus.type = BOOT_STATUS_INFO;\n+\tstatus.message = talloc_asprintf(conf, \"pxe: parsed config for %s\",\n+\t\t\t\t\tconf->dc->conf_url->host);\n+\tdevice_handler_boot_status(handler, &status);\n+\n+\ttalloc_free(buf);\n+out_clean:\n+\tif (result->cleanup_local)\n+\t\tunlink(result->local);\n+\ttalloc_free(conf);\n+}\n+\n+/**\n+ * Return a new conf_context and copy an existing discover_context under the\n+ * same talloc context.\n+ * @param ctx Parent talloc context\n+ * @param orig Original discover_context to copy\n+ * @return Pointer to new conf_context\n+ */\n+static struct conf_context *copy_context(void *ctx,\n+\t\t\t\t\t struct discover_context *orig)\n+{\n+\tstruct conf_context *conf;\n+\tstruct discover_context *dc;\n+\tstruct pxe_parser_info *info;\n+\n+\tconf = talloc_zero(ctx, struct conf_context);\n \n \tif (!conf)\n-\t\tgoto out;\n+\t\treturn NULL;\n \n-\tconf->dc = dc;\n \tconf->get_pair = conf_get_pair_space;\n \tconf->process_pair = pxe_process_pair;\n \tconf->finish = pxe_finish;\n+\tinfo = talloc_zero(conf, struct pxe_parser_info);\n+\tconf->parser_info = info;\n+\n+\t/*\n+\t * Small workaround for the test suite; pxe tests will call\n+\t * check_boot_option_count() which counts boot_options held by the\n+\t * discover_context, not the device_handler. Since the test suite will\n+\t * perform the pxe tests synchronously, just hold on to the original\n+\t * discover_context\n+\t */\n+#ifdef PETITBOOT_TEST\n+\tconf->dc = orig;\n+\treturn conf;\n+#endif\n+\n+\tdc = talloc(conf, struct discover_context);\n+\tdc->device = orig->device;\n+\tdc->network = orig->network;\n+\tdc->event = orig->event;\n+\tdc->test_data = orig->test_data;\n+\tdc->conf_url = pb_url_copy(dc, orig->conf_url);\n+\tlist_init(&dc->boot_options);\n \n-\tparser_info = talloc_zero(conf, struct pxe_parser_info);\n-\tconf->parser_info = parser_info;\n+\tconf->dc = dc;\n+\n+\treturn conf;\n+}\n+\n+static int pxe_parse(struct discover_context *dc)\n+{\n+\tstruct pb_url *pxe_base_url, *url;\n+\tchar **pxe_conf_files, **filename;\n+\tstruct conf_context *conf = NULL;\n+\tstruct load_url_result *result;\n+\tvoid *ctx = talloc_parent(dc);\n+\tbool complete_url;\n+\n+\t/* Expects dhcp event parameters to support network boot */\n+\tif (!dc->event)\n+\t\treturn -1;\n+\n+\t/*\n+\t * Retrieving PXE configs over the network can take some time depending\n+\t * on factors such as slow network, malformed paths, bad DNS, and\n+\t * overzealous firewalls. Instead of blocking the discover server while\n+\t * we wait for these, spawn an asynchronous job for each URL we can\n+\t * parse and process the resulting files in a callback.\n+\t * Since the caller will free the discover_context once\n+\t * iterate_parsers() completes, we need to copy the discover_context\n+\t * under a different talloc context so that it survives until the\n+\t * callback is finished with it.\n+\t */\n \n \tdc->conf_url = user_event_parse_conf_url(dc, dc->event, &complete_url);\n \tif (!dc->conf_url)\n-\t\tgoto out_conf;\n+\t\treturn -1;\n+\tconf = copy_context(ctx, dc);\n+\tif (!conf)\n+\t\treturn -1;\n \n \tif (complete_url) {\n \t\t/* we have a complete URL; use this and we're done. */\n-\t\trc = parser_request_url(dc, dc->conf_url, &buf, &len);\n-\t\tif (rc)\n+\t\tresult = load_url_async(conf->dc, conf->dc->conf_url,\n+\t\t\t\t\tpxe_conf_parse_cb, conf);\n+\t\tif (!result) {\n+\t\t\tpb_log(\"load_url_async fails for %s\\n\", dc->conf_url->path);\n \t\t\tgoto out_conf;\n+\t\t}\n \t} else {\n-\t\tpxe_conf_files = user_event_parse_conf_filenames(dc, dc->event);\n+\t\tpxe_conf_files = user_event_parse_conf_filenames(dc,\n+\t\t\t\t\t\t\t\tdc->event);\n \t\tif (!pxe_conf_files)\n \t\t\tgoto out_conf;\n \n-\t\trc = -1;\n-\n-\t\tpxe_base_url = pb_url_join(dc, dc->conf_url, pxelinux_prefix);\n+\t\tpxe_base_url = pb_url_join(dc, dc->conf_url,\n+\t\t\t\t\t pxelinux_prefix);\n \t\tif (!pxe_base_url)\n \t\t\tgoto out_pxe_conf;\n \n \t\tfor (filename = pxe_conf_files; *filename; filename++) {\n-\t\t\turl = pb_url_join(dc, pxe_base_url, *filename);\n+\t\t\tif (!conf) {\n+\t\t\t\tconf = copy_context(ctx, dc);\n+\t\t\t}\n+\t\t\turl = pb_url_join(conf->dc, pxe_base_url, *filename);\n \t\t\tif (!url)\n \t\t\t\tcontinue;\n-\n-\t\t\trc = parser_request_url(dc, url, &buf, &len);\n-\t\t\tif (!rc) /* found one, just break */\n-\t\t\t\tbreak;\n-\n-\t\t\ttalloc_free(url);\n+\t\t\tresult = load_url_async(conf, url, pxe_conf_parse_cb, conf);\n+\t\t\tif (!result) {\n+\t\t\t\tpb_log(\"load_url_async fails for %s\\n\",\n+\t\t\t\t conf->dc->conf_url->path);\n+\t\t\t\ttalloc_free(conf);\n+\t\t\t}\n+\t\t\t/* conf now needed by callback, don't reuse */\n+\t\t\tconf = NULL;\n \t\t}\n \n \t\ttalloc_free(pxe_base_url);\n-\n-\t\t/* No configuration file found on the boot server */\n-\t\tif (rc)\n-\t\t\tgoto out_pxe_conf;\n-\n \t\ttalloc_free(pxe_conf_files);\n \t}\n \n-\t/* Call the config file parser with the data read from the file */\n-\tconf_parse_buf(conf, buf, len);\n-\n-\ttalloc_free(buf);\n-\ttalloc_free(conf);\n-\n \treturn 0;\n \n out_pxe_conf:\n \ttalloc_free(pxe_conf_files);\n out_conf:\n \ttalloc_free(conf);\n-out:\n \treturn -1;\n }\n \ndiff --git a/lib/url/url.c b/lib/url/url.c\nindex 7202f49..6eeced3 100644\n--- a/lib/url/url.c\n+++ b/lib/url/url.c\n@@ -246,7 +246,7 @@ static void pb_url_update_full(struct pb_url *url)\n \turl->full = pb_url_to_string(url);\n }\n \n-static struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url)\n+struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url)\n {\n \tstruct pb_url *new_url;\n \ndiff --git a/lib/url/url.h b/lib/url/url.h\nindex 25e1ad8..9043615 100644\n--- a/lib/url/url.h\n+++ b/lib/url/url.h\n@@ -62,6 +62,7 @@ struct pb_url {\n \n bool is_url(const char *str);\n struct pb_url *pb_url_parse(void *ctx, const char *url_str);\n+struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url);\n struct pb_url *pb_url_join(void *ctx, const struct pb_url *url, const char *s);\n char *pb_url_to_string(struct pb_url *url);\n \n", "prefixes": [ "3/3" ] }