From patchwork Thu Mar 8 11:52:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Kiernan X-Patchwork-Id: 883085 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="UmijaLPl"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zxpn02XCgz9rxs for ; Thu, 8 Mar 2018 22:53:24 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 090FDC21E50; Thu, 8 Mar 2018 11:52:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9FA55C21F47; Thu, 8 Mar 2018 11:52:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 371FBC21E50; Thu, 8 Mar 2018 11:52:17 +0000 (UTC) Received: from mail-wm0-f66.google.com (mail-wm0-f66.google.com [74.125.82.66]) by lists.denx.de (Postfix) with ESMTPS id A213EC21C2C for ; Thu, 8 Mar 2018 11:52:16 +0000 (UTC) Received: by mail-wm0-f66.google.com with SMTP id w128so10838439wmw.0 for ; Thu, 08 Mar 2018 03:52:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bSV2CNpbs597U4ePs7jtRkLhxxkb1oYYvzpJplHlSP8=; b=UmijaLPl2kfF37ILFl2FYGjMTgeIwLF6fdNu5p6lqLMVpfzoML85N+okGvBtZXPlPh FHpYuVO1DVcgBFETpcY/J2eZecHuW9GW/3L8V8Lm0btPTjv+dThjPejh+bF7DADmoHEO ayiGwo8MOhV2gcVUOPZ+7p7B6MX+7iiViv+p6bn6SiUaS0tNcTMlRN9vMAOiTb9gKC+4 IzcGSJiYQ8HWilswdZ4OHl8TnB3+RU2/CqZ1h76uAB0RLQQe1XHlE4cmlIYmk5Q8R36u /DSpRtieYj9SWkShCMlEOgNj36K+CrxCJHwk2eJyZDy8trmTfPc+9PEgmUWGXmL9g18v 06Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bSV2CNpbs597U4ePs7jtRkLhxxkb1oYYvzpJplHlSP8=; b=QJUM9SvS841j5NFpRORVQsqqbUhx0wgY9vw81svJRK8c5IZ77v3hWQ2If8vTDCy668 XE3lFOz14/p7wIYN8vv0CR8pEI4BUGMxbxvn+leEuNNTXA65D5J0c0nfLuVkh/Z7jeZ8 WN6WJZZw+wxQKkX+Dj5Iqt9PqzfA64D4xf5ak+Q4dhe01iUNJLtNp4f7xZfgSVGobwWk DM3c95jDigzru2uuP/dLzUYBb8JW9ylaiFgz1gEi7Jf1KAtX+93ydHprxgcWQ0P761m9 AsX8I8kffRHn7ZBxZaJEeSFyDdI1wXTj3LEZI/bPaZQZleRhqX51zkMCc4z4nqjXN5oN mOpA== X-Gm-Message-State: AElRT7FahlBLH2arug62Ogok9mx/BzeZLJqJLNZ3dhnNCVfjBUI1X1zP PdhKGqa8F+7IdSOr51ig2P947G8t2P8= X-Google-Smtp-Source: AG47ELsR0qQW5vKqkwnt4empI71JPUCk0v9oatTxdAIV5X5WVA/uS7xDcGTEltq7nhWGp1cftf4Tlg== X-Received: by 10.28.116.17 with SMTP id p17mr18323578wmc.137.1520509936089; Thu, 08 Mar 2018 03:52:16 -0800 (PST) Received: from localhost.localdomain (cust246-dsl91-135-6.idnet.net. [91.135.6.246]) by smtp.gmail.com with ESMTPSA id x190sm17865859wme.27.2018.03.08.03.52.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 08 Mar 2018 03:52:15 -0800 (PST) From: Alex Kiernan To: u-boot@lists.denx.de Date: Thu, 8 Mar 2018 11:52:06 +0000 Message-Id: <1520509926-15837-3-git-send-email-alex.kiernan@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520509926-15837-1-git-send-email-alex.kiernan@gmail.com> References: <1520509926-15837-1-git-send-email-alex.kiernan@gmail.com> Cc: "xypron.glpk@gmx.de" , "S. Lockwood-Childs" Subject: [U-Boot] [PATCH 2/2] tools: env: Implement atomic replace for filesystem X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" If the U-Boot environment is stored in a regular file and redundant operation isn't set, then write to a temporary file and perform an atomic rename. Signed-off-by: Alex Kiernan --- tools/env/fw_env.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 2df3504..b814c4e 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1229,9 +1230,46 @@ static int flash_read (int fd) return 0; } +static int flash_open_tempfile(const char **dname, const char **target_temp) +{ + char *dup_name = strdup(DEVNAME (dev_current)); + char *temp_name = NULL; + int rc = -1; + + if (!dup_name) + return -1; + + *dname = dirname(dup_name); + if (!*dname) + goto err; + + rc = asprintf(&temp_name, "%s/uboot.tmp", *dname); + if (rc == -1) + goto err; + + rc = open(temp_name, O_RDWR | O_CREAT | O_TRUNC, 0700); + if (rc == -1) { + /* fall back to in place write */ + free(temp_name); + } else { + *target_temp = temp_name; + /* deliberately leak dup_name as dname /might/ point into + * it and we need it for our caller + */ + dup_name = NULL; + } + +err: + if (dup_name) + free(dup_name); + + return rc; +} + static int flash_io_write (int fd_current) { - int fd_target, rc, dev_target; + int fd_target = -1, rc, dev_target; + const char *dname, *target_temp = NULL; if (HaveRedundEnv) { /* switch to next partition for writing */ @@ -1247,8 +1285,17 @@ static int flash_io_write (int fd_current) goto exit; } } else { + struct stat sb; + + if (fstat(fd_current, &sb) == 0 && S_ISREG(sb.st_mode)) { + /* if any part of flash_open_tempfile() fails we fall + * back to in-place writes + */ + fd_target = flash_open_tempfile(&dname, &target_temp); + } dev_target = dev_current; - fd_target = fd_current; + if (fd_target == -1) + fd_target = fd_current; } rc = flash_write (fd_current, fd_target, dev_target); @@ -1260,7 +1307,7 @@ static int flash_io_write (int fd_current) DEVNAME (dev_current), strerror (errno)); } - if (HaveRedundEnv) { + if (fd_current != fd_target) { if (fsync(fd_target) && !(errno == EINVAL || errno == EROFS)) { fprintf (stderr, @@ -1275,6 +1322,34 @@ static int flash_io_write (int fd_current) strerror (errno)); rc = -1; } + + if (target_temp) { + int dir_fd; + + dir_fd = open(dname, O_DIRECTORY | O_RDONLY); + if (dir_fd == -1) + fprintf (stderr, + "Can't open %s: %s\n", + dname, strerror (errno)); + + if (rename(target_temp, DEVNAME(dev_target))) { + fprintf (stderr, + "rename failed %s => %s: %s\n", + target_temp, DEVNAME(dev_target), + strerror (errno)); + rc = -1; + } + + if (dir_fd != -1 && fsync(dir_fd)) + fprintf (stderr, + "fsync failed on %s: %s\n", + dname, strerror (errno)); + + if (dir_fd != -1 && close(dir_fd)) + fprintf (stderr, + "I/O error on %s: %s\n", + dname, strerror (errno)); + } } exit: return rc;