From patchwork Tue Sep 15 10:00:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 1364192 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::63e; helo=mail-ej1-x63e.google.com; envelope-from=swupdate+bncbcxploxj6ikrbu5bql5qkgqel6hfiny@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20161025 header.b=FzDpcgWl; dkim-atps=neutral Received: from mail-ej1-x63e.google.com (mail-ej1-x63e.google.com [IPv6:2a00:1450:4864:20::63e]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BrJdj0CNZz9sTH for ; Tue, 15 Sep 2020 20:00:55 +1000 (AEST) Received: by mail-ej1-x63e.google.com with SMTP id md9sf1060222ejb.8 for ; Tue, 15 Sep 2020 03:00:55 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1600164052; cv=pass; d=google.com; s=arc-20160816; b=QCKpV8NkUHO6c60SwQcU7ko+sRC9w4Ht9RYNV9lCAiWQq8LEnF2tYwCOV8TZ56Mkqp PuyleA/+xpnxI8CVbz5yO3ESnNzNTkiS9YxUB5JFf2KHQC4e1aS6YbNHKELhj44BKbfY 8dv9SYlnaXOOP5DhuupSrShTZ+6YJ0lHVZK+IXoTB90iA+ZFVRtNM++LpbfuPlnofEOI EStFmIM3sljj5W6ujqgGLYyVBWgCNh1W3sizTewobpGRi/ahqfLIZ30P9XyF+nuHM9AD RSF7Wp7ayd0t3raYvONZ1tA+ppEHL8JTvvlJoEtJYfDRkeI2isT8GPwHGWNkHGOoBv/m Hczw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:sender :dkim-signature; bh=svK5lkLidD+Mp/f8FkcCT9rz3AzEeaJ0zl9MuNLdLH0=; b=Fjkbi/Cxabq/0H4XWXGzebrmWHkG8YN6sVCkbmb6S4rPRRvZqjRC8Bkh0LfNtZig1s ++FfrS+4ystU4S3LtCWXkaVL8aAEIcBDzPHW/zLAroNKc6hKuNmBs7B4BbhkCtWt40T3 xO6l9jvea5ZUlMjF19jPRi1mQegvn6gh8J52qZGXg5kTehvjIvcYg2+nwAfmnlm4dIaO 7D230QhG4LdRbIs5SYy/u+4vLBlPQkpz9NITLkkuDwbcAjJZcQULV3/ck2kXyOGTap7M +8frPVihy7cZKLfdE1HIqbT8/13VIak7p1AEms4W1gaLCGX1vRgBsNwPf16rVYscUBhy Spfw== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-subscribe:list-unsubscribe; bh=svK5lkLidD+Mp/f8FkcCT9rz3AzEeaJ0zl9MuNLdLH0=; b=FzDpcgWlNTos9yoLhFiU2aBHlsKSaE4UuHP4jnz91xty7oyIPW7hJFDT7NYtHpW+ZN OLeDtuSzFZCKCMCrR50PVWNt4TOsQuSdmDpi3BCztikulerApHFB3j6+cXRr8KCsg9HR iXdFaEC2O70TU0VsgxkB4yqHXsLmY6ZvFMA3TvELw1Rzfd4mBCT1IsUB6xobDwtzHhKd cwLlFcSvBERjymLeYu6RCjbb5URZunr2PzRuTtnxchnI6He+EvLrSdkIio8+PeCJBOYR WrcS6EZVbWNPI2NqZftgV0s6Gi4X2tUT5a16uWxKoQL++SxrRXhuUjkXmEEO2LxNFu+T /ztw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=svK5lkLidD+Mp/f8FkcCT9rz3AzEeaJ0zl9MuNLdLH0=; b=NLyrXrp0jC0nVJUkGOWtxd/+rgm31OJwP30zmCDbZxb/PE1NXkLgD9TKW1jSkOpOGi 2jcBkUH/eF63VNaV4bADwCxPdR0Xkjbc4aAoxDwwrKfXdHIBjRkpPYV8ybfQ2xtfXTG4 so5KCSzwh7FSm9CZM66AYdzy1CBAybYDmNpf+C4LcsWoUKcf/5BL+Ah5FSew5gGZ1TqB RW+hX9yismIQ1ZBy7dJdpQNyXbsiHSyOoojJ/ez65EBnHioPg2o6ADTSj2kuoFocKWTr l715RqIEc8HhTqPLU2PdxRfCdERq7OMlDxDxHsBLJgLvY/Rb8xnkHKrJMThZ1iPP3o9W r8kw== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM530MiNwaCph3yTHw3bCTxD8YLGTiim2gzgUSaAPDU/82ACrEq6RQ Pn+ryYIYILSv64GjUfZfJ2Q= X-Google-Smtp-Source: ABdhPJzaTqFffQpSfpKxJdD75kFCokIDf4R2SAEtzi7oHdv9sTrAigEBA3/bFzknezFMPBi8xdy2Ug== X-Received: by 2002:a50:bb0d:: with SMTP id y13mr22422255ede.317.1600164052230; Tue, 15 Sep 2020 03:00:52 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a50:bc05:: with SMTP id j5ls2333659edh.0.gmail; Tue, 15 Sep 2020 03:00:51 -0700 (PDT) X-Received: by 2002:a05:6402:28d:: with SMTP id l13mr22209654edv.293.1600164051026; Tue, 15 Sep 2020 03:00:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600164051; cv=none; d=google.com; s=arc-20160816; b=0sH+zuu70HhlkwIZFSHxzQNtplfigxjq8xed6+xOtsgQSqUIC+g0pD+U/GgMMYavkR XFJrt2B3PVFs+JQFCY9ma64CpTBQLDHw8ATdf7CdBQ1vGi7B98DKaBlNUBrwl7QgHPlW 2+YK6HXVFLrj32megyYheqxICU5XfLCYWcPb4IUI8gKIyUF50twvWT7qbFbIaprz6jOt KYc3iyvXkFAGL94WDSUu2W4yN9vBEn3TpgFr/UQxe7a55jlJwMperdc7NYCKZuRDXkTZ pcrvueqOE7FNlZXdx8qWKZlXFq2U9BFB4mM1iBmgahFVN+B5mk2Rgt3RWLJ6YN+QfmOc fDAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from; bh=lxYCSVjgqpCjQF8cnpn7PJ87nMYxjl/gNjV0eY+W7rA=; b=XuiEwISjQDjMnSywZ4JUWQ0mUKkuewHt7ewYo2BERSwJnxtQ5/ku8tPS8j7mH+5tKa j5zofq5RU59DXaGCpZ2W/Jw4281vNafxSisH5nvIxKb5NMAJMhNUiGfWlN0OyMIPRwRE ZjoKuunA4uFTnY1J3rpCv5aJH3BVveYadvKSZqHbp/hXkBswTJnBjnqO8y5d2d4HdnZX IOU8ap5JDlN89Oafx+fRez0L0MFbt6BFp1Ntuc5agIXJhpA7rFyXVYL390d0CM8V1nH8 qX1Ukd7CD+RsUijEyztmP0FCRdpoRrA6tT/wGFMcYTUPwQb1Tp2quKqiSWnrpSSUo4qr 8Rxg== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Received: from mail-out.m-online.net (mail-out.m-online.net. [212.18.0.9]) by gmr-mx.google.com with ESMTPS id a16si669978ejk.1.2020.09.15.03.00.50 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 Sep 2020 03:00:51 -0700 (PDT) Received-SPF: neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) client-ip=212.18.0.9; Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 4BrJdZ5X9bz1qs3k; Tue, 15 Sep 2020 12:00:50 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 4BrJdZ5JyZz1qyXV; Tue, 15 Sep 2020 12:00:50 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id T-myF0AwxsC3; Tue, 15 Sep 2020 12:00:49 +0200 (CEST) Received: from babic.homelinux.org (host-88-217-136-221.customer.m-online.net [88.217.136.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPS; Tue, 15 Sep 2020 12:00:49 +0200 (CEST) Received: from localhost (mail.babic.homelinux.org [127.0.0.1]) by babic.homelinux.org (Postfix) with ESMTP id 56FCE4540601; Tue, 15 Sep 2020 12:00:49 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at babic.homelinux.org Received: from babic.homelinux.org ([IPv6:::1]) by localhost (mail.babic.homelinux.org [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id paHrXMBhcGR1; Tue, 15 Sep 2020 12:00:46 +0200 (CEST) Received: from paperino.fritz.box (paperino.fritz.box [192.168.178.64]) by babic.homelinux.org (Postfix) with ESMTP id AF71D45405DC; Tue, 15 Sep 2020 12:00:46 +0200 (CEST) From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH V2] diskpart: do not write to disk if partitions do not change Date: Tue, 15 Sep 2020 12:00:46 +0200 Message-Id: <20200915100046.44453-1-sbabic@denx.de> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Original-Sender: sbabic@denx.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Do not write to the disk if the partition table is the same as the one on disk. Implement a comparison based on the following parameters: - partition number - partition type - start address - size If one of them is changed, the whole partition table is written to the disk. Signed-off-by: Stefano Babic --- Changes since V1: - set default GUID for GPT in case no one or a wrong is passed handlers/diskpart_handler.c | 169 +++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 33 deletions(-) diff --git a/handlers/diskpart_handler.c b/handlers/diskpart_handler.c index 5f4d777..8dd0e24 100644 --- a/handlers/diskpart_handler.c +++ b/handlers/diskpart_handler.c @@ -26,6 +26,10 @@ void diskpart_handler(void); */ #define LIBFDISK_INIT_UNDEF(_x) ((__typeof__(_x)) -1) +/* Linux native partition type */ + #define GPT_DEFAULT_ENTRY_TYPE "0FC63DAF-8483-4772-8E79-3D69D8477DE4" + + /** * Keys for the properties field in sw-description */ @@ -69,17 +73,13 @@ struct hnd_priv { * * return 0 if ok */ -static int diskpart_set_partition(struct fdisk_context *cxt, - struct fdisk_partition *pa, - struct partition_data *part) +static int diskpart_set_partition(struct fdisk_partition *pa, + struct partition_data *part, + unsigned long sector_size, + struct fdisk_parttype *parttype) { - unsigned long sector_size = fdisk_get_sector_size(cxt); - struct fdisk_label *lb; - struct fdisk_parttype *parttype = NULL; int ret = 0; - lb = fdisk_get_label(cxt, NULL); - if (!sector_size) sector_size = 1; fdisk_partition_unset_partno(pa); @@ -94,21 +94,41 @@ static int diskpart_set_partition(struct fdisk_context *cxt, if (part->size != LIBFDISK_INIT_UNDEF(part->size)) ret |= fdisk_partition_set_size(pa, part->size / sector_size); - /* - * GPT uses strings instead of hex code for partition type - */ - if (fdisk_is_label(cxt, GPT)) { - parttype = fdisk_label_get_parttype_from_string(lb, part->type); - } else if (fdisk_is_label(cxt, DOS)) { - parttype = fdisk_label_get_parttype_from_code(lb, ustrtoull(part->type, 16)); - } else - WARN("Partition type set just for GPT or DOS"); - if (parttype) ret |= fdisk_partition_set_type(pa, parttype); + return ret; } +/* + * Return true if partition differs + */ +static bool diskpart_partition_cmp(const char *lbtype, struct fdisk_partition *firstpa, struct fdisk_partition *secondpa) +{ + if (!firstpa || !secondpa) + return true; + + if (firstpa && secondpa && (fdisk_partition_cmp_partno(firstpa, secondpa) || + fdisk_partition_cmp_start(firstpa, secondpa) || + (!strcmp(lbtype, "gpt") && + (strcmp(fdisk_parttype_get_string(fdisk_partition_get_type(firstpa)), + fdisk_parttype_get_string(fdisk_partition_get_type(secondpa))) || + strcmp(fdisk_partition_get_name(firstpa) ? fdisk_partition_get_name(firstpa) : "", + fdisk_partition_get_name(secondpa) ? fdisk_partition_get_name(secondpa) : ""))) || + (!strcmp(lbtype, "dos") && + fdisk_parttype_get_code(fdisk_partition_get_type(firstpa)) != + fdisk_parttype_get_code(fdisk_partition_get_type(secondpa))) || + fdisk_partition_get_size(firstpa) != fdisk_partition_get_size(secondpa))) { + TRACE("Partition differ : %s(%lu) <--> %s(%lu)", + fdisk_partition_get_name (firstpa) ? fdisk_partition_get_name(firstpa) : "", + fdisk_partition_get_size(firstpa), + fdisk_partition_get_name(secondpa) ? fdisk_partition_get_name(secondpa) : "", + fdisk_partition_get_size(secondpa)); + return true; + } + return false; +} + static int diskpart(struct img_type *img, void __attribute__ ((__unused__)) *data) { @@ -118,11 +138,15 @@ static int diskpart(struct img_type *img, struct fdisk_context *cxt; struct partition_data *part; struct partition_data *tmp; + struct fdisk_table *tb = NULL; + struct fdisk_table *oldtb = NULL; + struct fdisk_parttype *parttype = NULL; int ret = 0; - int i; + unsigned long i; struct hnd_priv priv = {FDISK_DISKLABEL_DOS}; + bool createtable = false; - if (lbtype && strcmp(lbtype, "gpt") && strcmp(lbtype, "dos")) { + if (!lbtype || (strcmp(lbtype, "gpt") && strcmp(lbtype, "dos"))) { ERROR("Just GPT or DOS partition table are supported"); return -EINVAL; } @@ -221,6 +245,7 @@ static int diskpart(struct img_type *img, LIST_INSERT_BEFORE(p, part, next); } } + /* * Check partition table */ @@ -228,6 +253,7 @@ static int diskpart(struct img_type *img, WARN("%s does not contain a recognized partition table", img->device); fdisk_create_disklabel(cxt, lbtype); + createtable = true; } else if (lbtype) { if (!strcmp(lbtype, "gpt")) priv.labeltype = FDISK_DISKLABEL_GPT; @@ -238,43 +264,120 @@ static int diskpart(struct img_type *img, WARN("Partition table of different type, setting to %s, all data lost !", lbtype); fdisk_create_disklabel(cxt, lbtype); + createtable = true; } } - i = 0; + struct fdisk_label *lb = fdisk_get_label(cxt, NULL); + unsigned long sector_size = fdisk_get_sector_size(cxt); + + /* + * Create a new in-memory partition taböe to be compared + * with the table on the disk, and applied if differs + */ + tb = fdisk_new_table(); + + if (fdisk_get_partitions(cxt, &oldtb)) + createtable = true; + + if (!tb) { + ERROR("OOM creating new table !"); + ret = -ENOMEM; + goto handler_exit; + } - fdisk_delete_all_partitions(cxt); + i = 0; LIST_FOREACH(part, &priv.listparts, next) { - struct fdisk_partition *pa = NULL; - size_t partno; struct fdisk_partition *newpa; newpa = fdisk_new_partition(); - ret = diskpart_set_partition(cxt, newpa, part); + /* + * GPT uses strings instead of hex code for partition type + */ + if (fdisk_is_label(cxt, GPT)) { + parttype = fdisk_label_get_parttype_from_string(lb, part->type); + if (!parttype) + parttype = fdisk_label_get_parttype_from_string(lb, GPT_DEFAULT_ENTRY_TYPE); + } else { + parttype = fdisk_label_get_parttype_from_code(lb, ustrtoull(part->type, 16)); + } + ret = diskpart_set_partition(newpa, part, sector_size, parttype); if (ret) { WARN("I cannot set all partition's parameters"); } - if ((ret = fdisk_add_partition(cxt, newpa, &partno)) < 0) { + if ((ret = fdisk_table_add_partition(tb, newpa)) < 0) { ERROR("I cannot add partition %zu(%s): %d", part->partno, part->name, ret); } fdisk_unref_partition(newpa); if (ret < 0) goto handler_exit; - fdisk_reset_partition(pa); i++; } /* - * Everything done, write into disk + * A partiton table was found on disk, now compares the two tables + * to check if they differ. */ - ret = fdisk_write_disklabel(cxt); - if (ret) - ERROR("Partition table cannot be written on disk"); - if (fdisk_reread_partition_table(cxt)) - WARN("Table cannot be reread from the disk, be careful !"); + if (!createtable) { + size_t numpartondisk = fdisk_table_get_nents(oldtb); + + if (numpartondisk != i) { + TRACE("Number of partitions differs on disk: %lu <--> requested: %lu", numpartondisk, i); + createtable = true; + } else { + struct fdisk_partition *pa, *newpa; + struct fdisk_iter *itr = fdisk_new_iter(FDISK_ITER_FORWARD); + struct fdisk_iter *olditr = fdisk_new_iter(FDISK_ITER_FORWARD); + + i = 0; + while (i < numpartondisk && !createtable) { + newpa=NULL; + pa = NULL; + if (fdisk_table_next_partition (tb, itr, &newpa) || + fdisk_table_next_partition (oldtb, olditr, &pa)) { + TRACE("Partition not found, something went wrong %lu !", i); + ret = -EFAULT; + goto handler_exit; + } + if (diskpart_partition_cmp(lbtype, pa, newpa)) { + createtable = true; + } + + fdisk_unref_partition(newpa); + fdisk_unref_partition(pa); + i++; + } + } + } + + if (createtable) { + TRACE("Partitions on disk differ, write to disk;"); + fdisk_delete_all_partitions(cxt); + ret = fdisk_apply_table(cxt, tb); + if (ret) { + ERROR("Partition table cannot be applied !"); + goto handler_exit; + } + + /* + * Everything done, write into disk + */ + ret = fdisk_write_disklabel(cxt); + if (ret) + ERROR("Partition table cannot be written on disk"); + if (fdisk_reread_partition_table(cxt)) + WARN("Table cannot be reread from the disk, be careful !"); + } else { + ret = 0; + TRACE("Same partition table on disk, do not touch partition table !"); + } handler_exit: + if (tb) + fdisk_unref_table(tb); + if (oldtb) + fdisk_unref_table(oldtb); if (fdisk_deassign_device(cxt, 0)) WARN("Error deassign device %s", img->device);