From patchwork Fri Aug 31 03:58:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ernesto_A=2E_Fern=C3=A1ndez?= X-Patchwork-Id: 10583079 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5036514BD for ; Fri, 31 Aug 2018 03:58:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FC572BD3F for ; Fri, 31 Aug 2018 03:58:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 32B432BD94; Fri, 31 Aug 2018 03:58:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CF4792BD3F for ; Fri, 31 Aug 2018 03:58:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727139AbeHaIDt (ORCPT ); Fri, 31 Aug 2018 04:03:49 -0400 Received: from mail-qt0-f196.google.com ([209.85.216.196]:46800 "EHLO mail-qt0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726974AbeHaIDs (ORCPT ); Fri, 31 Aug 2018 04:03:48 -0400 Received: by mail-qt0-f196.google.com with SMTP id d4-v6so13160755qtn.13 for ; Thu, 30 Aug 2018 20:58:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :content-transfer-encoding; bh=yQPyyF/ucUtxOonlryyUA9MvB5i9ABogHw+FF7xuVls=; b=h0tmfGmnwy7+Kbe29S0fD2XWn7bix7KlZ07jlV27D4W++P/eMWETcDdvSo5qrW8n31 Lo1pvbeNW1QdXRhMMoAhAUgXeU9e7vcXEp+aE33ta0i7sgVl//Kq5Z3opq3pe/2uVAYn h9gSwyAZQvMvKf4NKSazYIlm/IGeaWS/HyHx7Dix3OSFBPH9oyJbjNf7FdBc8JzMR62n T7iNW0P9RXuEEBEWmAWwR1Rta9yzWVrlED2YRObXYq6oAdB2HDdJ5+gZDRAGKK3MdZ/p wTIRfcZG/ZtFkERizFMRw3bE5tKx6mwc8vCtH24ZvT3n9Zl6/564VsMdi3Bl0h/3G06C Jiag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:content-transfer-encoding; bh=yQPyyF/ucUtxOonlryyUA9MvB5i9ABogHw+FF7xuVls=; b=ALbsmnz2WoFgedzxAbPejvKAh3O84HYzy+J+wBAVhQ0cACiQTgFlwLzTuZV/Yp97An PaGretkHVnDIDQMbPhfOppiwZKgFP2xUyAFfn2mZwoNpWiQfcZRhfuvmegHXoEp2FhQL pjcljdKv0Edvt7edVy5d0J/+X/Amy4IlFXYtkZsEBcwH1csQC9Q0iPdI+I70dYRNo6Ns XTXj/WwQElM+6ARY89f1KJrJxRhY3p8ujR2Im97/DHW2pF/GcwJO9KxIqPZXTL6WFsHJ wndfDDjgPWeAl+qgdqCVe1wvq+OfUzs4ZuJuzannQGc1qtENnzmAEv3+f9ZRCQjdzcn8 FGtQ== X-Gm-Message-State: APzg51AzMnoXFrFys42yRKt8iH0YO7Bcq+dFIkPct2xIigJi8wvk3m3J fZLT8uXb7rjr/s+o7TIy277dcddH X-Google-Smtp-Source: ANB0VdYeCJipMFXHkIZTQHtjfVK15ijQCKGdUQLEFa7Qidoa7ChtqqwyqNCBVxWo+1FmlcAYeBt9ng== X-Received: by 2002:ac8:392e:: with SMTP id s43-v6mr14318512qtb.68.1535687904768; Thu, 30 Aug 2018 20:58:24 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id b134-v6sm5350530qka.63.2018.08.30.20.58.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Aug 2018 20:58:24 -0700 (PDT) Date: Fri, 31 Aug 2018 00:58:19 -0300 From: Ernesto =?utf-8?q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton Subject: [PATCH 1/6] hfsplus: prevent btree data loss on root split Message-ID: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> MIME-Version: 1.0 Content-Disposition: inline Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Creating, renaming or deleting a file may cause catalog corruption and data loss. This bug is randomly triggered by xfstests generic/027, but here is a faster reproducer: truncate -s 50M fs.iso mkfs.hfsplus fs.iso mount fs.iso /mnt i=100 while [ $i -le 150 ]; do touch /mnt/$i &>/dev/null ((++i)) done i=100 while [ $i -le 150 ]; do mv /mnt/$i /mnt/$(perl -e "print $i x82") &>/dev/null ((++i)) done umount /mnt fsck.hfsplus -n fs.iso The bug is triggered whenever hfs_brec_update_parent() needs to split the root node. The height of the btree is not increased, which leaves the new node orphaned and its records lost. Signed-off-by: Ernesto A. Fernández --- fs/hfsplus/brec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index ed8eacb34452..aa17a392b414 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c @@ -429,6 +429,10 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) if (new_node) { __be32 cnid; + if (!new_node->parent) { + hfs_btree_inc_height(tree); + new_node->parent = tree->root; + } fd->bnode = hfs_bnode_find(tree, new_node->parent); /* create index key and entry */ hfs_bnode_read_key(new_node, fd->search_key, 14); From patchwork Fri Aug 31 03:59:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ernesto_A=2E_Fern=C3=A1ndez?= X-Patchwork-Id: 10583081 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B056714BD for ; Fri, 31 Aug 2018 03:59:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0F1E2BD94 for ; Fri, 31 Aug 2018 03:59:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 939492BDC8; Fri, 31 Aug 2018 03:59:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 470622BD94 for ; Fri, 31 Aug 2018 03:59:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727197AbeHaIFI (ORCPT ); Fri, 31 Aug 2018 04:05:08 -0400 Received: from mail-qk1-f195.google.com ([209.85.222.195]:43742 "EHLO mail-qk1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726974AbeHaIFI (ORCPT ); Fri, 31 Aug 2018 04:05:08 -0400 Received: by mail-qk1-f195.google.com with SMTP id 130-v6so619373qkd.10 for ; Thu, 30 Aug 2018 20:59:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=OJFs6gF3+e58cXu72JYPTumN7Q0KTEPJT/Uillr6/Vo=; b=EsskqemcLm+IO4O9xvtjE4kKaomb/4Dg2qVSoSPyKdGgOhX4YrBcNr3BucNwGXbkdT XHa439lhCZLmu+tPF7R7w1jx8oIoGtGXfyQ2hMFkgSvtvwkbTGYiK235q1TffvBZWWBs rwwSa0iNsxuQuJdV9xWOo/P21p/8Vqzu/B2SIdd7hpNmnl5evEZ4K6Br0MPbl8LDht+k +TsTIuYPQPGBm8CfPn6KoCWDWJGlpBU4S9O+NWUo1XTQXN6iS11TJ7FTOezbdZ6/rxez JiHpD0fSov6+VY/CbE6EQOfgfy1EfCNGQLPQUzLnEaZs68oIKpIwZub9sznelSKpcoNJ eX9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=OJFs6gF3+e58cXu72JYPTumN7Q0KTEPJT/Uillr6/Vo=; b=tN8gaEAUbjgeMnHEgoAhch1R/rJmeFMax5PsNGDkGENsEn0yMwpcBHqSq0ZZ49G4Rm 71MDuVLHd8h+wO1+VPF1A9h8K3V2V/H3tG1HvI7obUg6wn+8erWKx9tfo6j9rENaVrMA 6ZIRijl2yaJoM/bgMfjsjbOp9u9NxUKaG71ruq15662vq9rg7pEci5PvoiQKnrxJk1gS 1WHMD1wjNeUfxMtEV5TYpI4Zq8bYUKwmrQ/gr8llMZYl/Htbsi86Qu6X9v6cYqYZLqcb 7JCvsJAhDjDA3ioTuQlx1ttmHfsXScPs8XmXaa7NZ/syw4uj6w5OfrHnb1Sz6v3edZvu tydA== X-Gm-Message-State: APzg51B3yQXt6G0hpC0RmQjlyPngVbq5p9tEF9dDokqnd9nvpFTbdlqD ZYahD0pE1zpOsBm8B6zk45aEpf/O X-Google-Smtp-Source: ANB0VdZXl4PJjkPXSrwTxqhd4RuSzq2UtyIjxYGScs6sRjNSXNklyWX1SmpoGx/c1W4x0FRDLqQj/g== X-Received: by 2002:a37:d0c:: with SMTP id 12-v6mr13801270qkn.148.1535687983008; Thu, 30 Aug 2018 20:59:43 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id v50-v6sm5693118qtc.28.2018.08.30.20.59.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Aug 2018 20:59:42 -0700 (PDT) Date: Fri, 31 Aug 2018 00:59:39 -0300 From: Ernesto =?utf-8?q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton Subject: [PATCH 2/6] hfsplus: fix BUG on bnode parent update Message-ID: <5ee1db09b60373a15890f6a7c835d00e76bf601d.1535682461.git.ernesto.mnd.fernandez@gmail.com> References: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Creating, renaming or deleting a file may hit BUG_ON() if the first record of both a leaf node and its parent are changed, and if this forces the parent to be split. This bug is triggered by xfstests generic/027, somewhat rarely; here is a more reliable reproducer: truncate -s 50M fs.iso mkfs.hfsplus fs.iso mount fs.iso /mnt i=1000 while [ $i -le 2400 ]; do touch /mnt/$i &>/dev/null ((++i)) done i=2400 while [ $i -ge 1000 ]; do mv /mnt/$i /mnt/$(perl -e "print $i x61") &>/dev/null ((--i)) done The issue is that a newly created bnode is being put twice. Reset new_node to NULL in hfs_brec_update_parent() before reaching goto again. Signed-off-by: Ernesto A. Fernández --- fs/hfsplus/brec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index aa17a392b414..1918544a7871 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c @@ -449,6 +449,7 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) /* restore search_key */ hfs_bnode_read_key(node, fd->search_key, 14); } + new_node = NULL; } if (!rec && node->parent) From patchwork Fri Aug 31 04:00:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ernesto_A=2E_Fern=C3=A1ndez?= X-Patchwork-Id: 10583087 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 48FEF14BD for ; Fri, 31 Aug 2018 04:00:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 373FE2BD41 for ; Fri, 31 Aug 2018 04:00:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2B13A2BD95; Fri, 31 Aug 2018 04:00:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8DA6A2BD41 for ; Fri, 31 Aug 2018 04:00:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727202AbeHaIFs (ORCPT ); Fri, 31 Aug 2018 04:05:48 -0400 Received: from mail-qt0-f194.google.com ([209.85.216.194]:39611 "EHLO mail-qt0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726974AbeHaIFs (ORCPT ); Fri, 31 Aug 2018 04:05:48 -0400 Received: by mail-qt0-f194.google.com with SMTP id o15-v6so13178232qtk.6 for ; Thu, 30 Aug 2018 21:00:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=zv8uHvlKfuNScpsBGLYaete10lXSf6rzeWHrAI4jh+8=; b=JqO1oNqCBlBCVbMAYt7DlsierhTndBAPXumCLchoBY6Ds/a6rDU+RC8urqS8FJW7eC Pd7277gYdpA5EnvuDBj0ao3wQJp0tbLiQMf1aKqpSR9Dkf912T8XwPX2MyN2mV57CH/s iMevF2dbfvuoSW9L+wAeLXhYjAH9H1rP9JE4eRul+bF7fKxeypbPzLh7jlk14Z6KU2CY gaNij2RK3EGiYlbqY4mLy8To8zD1F+MwM8YSQpbCHBm3drhba84F0Ty7VvBF2Kr0tKcu 9Xq9j/C2QXqQYEH4VWBbq7C46Pcvb+xsFafJJPJuiDcsaU5S2/Gzw2WUQiDXjyykJUyt /Hfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=zv8uHvlKfuNScpsBGLYaete10lXSf6rzeWHrAI4jh+8=; b=QJ4Ap9umcgaPz45Xobe4XCg/RrU2PMZJXEoS82pWMopnsJ11t0nEBEP4whFBxHdNFf 9F8TDGZXfkjGFi3MhitMOjVPpJPQndXd7BLulA624E8+F/LmVjgWrPjUWaNPYEAa+VJD wbhraiP3NIcqrvERIRWkH8yrUKf2B+iyUcCeDZ0VDPEM+doMSUfg5wrciNCyY5IbtKxf TWilTvayrndhQscw3xILv5ErVbZl5lWIvCQzHfd2IBtAbFp+tTG6vxkIslWgDNeaaq3e l8EGeX5/sIevqczkfKn4V+HyjukV1WBhFJ960fA0bhCL4jqa4S4FXk1nEVfyQDlcLia/ 3Q4w== X-Gm-Message-State: APzg51DCFuvxuy1YaI5gb4T8I558p4q6wN3i5cvUARn5Xxp1PDprNyUm 8ThgTpvMUz2+AKZQVtlKusmCGHfO X-Google-Smtp-Source: ANB0VdadtrzW7J3/HDkYLtBU3dC4UScp/wvj5FCvGBbq7FZendxrkLezpQHaFQwiVAxIjBaOGNLXtw== X-Received: by 2002:aed:39ea:: with SMTP id m97-v6mr14557089qte.30.1535688021922; Thu, 30 Aug 2018 21:00:21 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id a66-v6sm4914171qkf.96.2018.08.30.21.00.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Aug 2018 21:00:21 -0700 (PDT) Date: Fri, 31 Aug 2018 01:00:17 -0300 From: Ernesto =?utf-8?q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton Subject: [PATCH 3/6] hfsplus: prevent btree data loss on ENOSPC Message-ID: <4ecd0a1d09756aadb173809e18285e807994e90b.1535682462.git.ernesto.mnd.fernandez@gmail.com> References: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Inserting or deleting a record in a btree may require splitting several of its nodes. If we hit ENOSPC halfway through, the new nodes will be left orphaned and their records will be lost. This could mean lost inodes, extents or xattrs. From now on, check the available disk space before making any changes. This still leaves the potential problem of corruption on ENOMEM. The patch can be tested with xfstests generic/027. Signed-off-by: Ernesto A. Fernández --- fs/hfsplus/attributes.c | 10 ++++++++++ fs/hfsplus/btree.c | 42 +++++++++++++++++++++++++++--------------- fs/hfsplus/catalog.c | 24 ++++++++++++++++++++++++ fs/hfsplus/extents.c | 4 ++++ fs/hfsplus/hfsplus_fs.h | 2 ++ 5 files changed, 67 insertions(+), 15 deletions(-) diff --git a/fs/hfsplus/attributes.c b/fs/hfsplus/attributes.c index 2bab6b3cdba4..e6d554476db4 100644 --- a/fs/hfsplus/attributes.c +++ b/fs/hfsplus/attributes.c @@ -217,6 +217,11 @@ int hfsplus_create_attr(struct inode *inode, if (err) goto failed_init_create_attr; + /* Fail early and avoid ENOSPC during the btree operation */ + err = hfs_bmap_reserve(fd.tree, fd.tree->depth + 1); + if (err) + goto failed_create_attr; + if (name) { err = hfsplus_attr_build_key(sb, fd.search_key, inode->i_ino, name); @@ -313,6 +318,11 @@ int hfsplus_delete_attr(struct inode *inode, const char *name) if (err) return err; + /* Fail early and avoid ENOSPC during the btree operation */ + err = hfs_bmap_reserve(fd.tree, fd.tree->depth); + if (err) + goto out; + if (name) { err = hfsplus_attr_build_key(sb, fd.search_key, inode->i_ino, name); diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index de14b2b6881b..d20902f3e015 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c @@ -342,26 +342,21 @@ static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx) return node; } -struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) +/* Make sure @tree has enough space for the @rsvd_nodes */ +int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes) { - struct hfs_bnode *node, *next_node; - struct page **pagep; - u32 nidx, idx; - unsigned off; - u16 off16; - u16 len; - u8 *data, byte, m; - int i; + struct inode *inode = tree->inode; + struct hfsplus_inode_info *hip = HFSPLUS_I(inode); + u32 count; + int res; - while (!tree->free_nodes) { - struct inode *inode = tree->inode; - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); - u32 count; - int res; + if (rsvd_nodes <= 0) + return 0; + while (tree->free_nodes < rsvd_nodes) { res = hfsplus_file_extend(inode, hfs_bnode_need_zeroout(tree)); if (res) - return ERR_PTR(res); + return res; hip->phys_size = inode->i_size = (loff_t)hip->alloc_blocks << HFSPLUS_SB(tree->sb)->alloc_blksz_shift; @@ -372,6 +367,23 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) tree->free_nodes = count - tree->node_count; tree->node_count = count; } + return 0; +} + +struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) +{ + struct hfs_bnode *node, *next_node; + struct page **pagep; + u32 nidx, idx; + unsigned off; + u16 off16; + u16 len; + u8 *data, byte, m; + int i, res; + + res = hfs_bmap_reserve(tree, 1); + if (res) + return ERR_PTR(res); nidx = 0; node = hfs_bnode_find(tree, nidx); diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index a196369ba779..35472cba750e 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c @@ -265,6 +265,14 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, if (err) return err; + /* + * Fail early and avoid ENOSPC during the btree operations. We may + * have to split the root node at most once. + */ + err = hfs_bmap_reserve(fd.tree, 2 * fd.tree->depth); + if (err) + goto err2; + hfsplus_cat_build_key_with_cnid(sb, fd.search_key, cnid); entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? @@ -333,6 +341,14 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str) if (err) return err; + /* + * Fail early and avoid ENOSPC during the btree operations. We may + * have to split the root node at most once. + */ + err = hfs_bmap_reserve(fd.tree, 2 * (int)fd.tree->depth - 2); + if (err) + goto out; + if (!str) { int len; @@ -433,6 +449,14 @@ int hfsplus_rename_cat(u32 cnid, return err; dst_fd = src_fd; + /* + * Fail early and avoid ENOSPC during the btree operations. We may + * have to split the root node at most twice. + */ + err = hfs_bmap_reserve(src_fd.tree, 4 * (int)src_fd.tree->depth - 1); + if (err) + goto out; + /* find the old dir entry and read the data */ err = hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name); diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 8e0f59767694..8a8893d522ef 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -100,6 +100,10 @@ static int __hfsplus_ext_write_extent(struct inode *inode, if (hip->extent_state & HFSPLUS_EXT_NEW) { if (res != -ENOENT) return res; + /* Fail early and avoid ENOSPC during the btree operation */ + res = hfs_bmap_reserve(fd->tree, fd->tree->depth + 1); + if (res) + return res; hfs_brec_insert(fd, hip->cached_extents, sizeof(hfsplus_extent_rec)); hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW); diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 8e039435958a..dd7ad9f13e3a 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -311,6 +311,7 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb) #define hfs_btree_open hfsplus_btree_open #define hfs_btree_close hfsplus_btree_close #define hfs_btree_write hfsplus_btree_write +#define hfs_bmap_reserve hfsplus_bmap_reserve #define hfs_bmap_alloc hfsplus_bmap_alloc #define hfs_bmap_free hfsplus_bmap_free #define hfs_bnode_read hfsplus_bnode_read @@ -395,6 +396,7 @@ u32 hfsplus_calc_btree_clump_size(u32 block_size, u32 node_size, u64 sectors, struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id); void hfs_btree_close(struct hfs_btree *tree); int hfs_btree_write(struct hfs_btree *tree); +int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes); struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree); void hfs_bmap_free(struct hfs_bnode *node); From patchwork Fri Aug 31 04:00:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ernesto_A=2E_Fern=C3=A1ndez?= X-Patchwork-Id: 10583089 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 05C3E920 for ; Fri, 31 Aug 2018 04:00:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EA64A2BD41 for ; Fri, 31 Aug 2018 04:00:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DEEFA2BD95; Fri, 31 Aug 2018 04:00:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9418A2BD41 for ; Fri, 31 Aug 2018 04:00:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727227AbeHaIGU (ORCPT ); Fri, 31 Aug 2018 04:06:20 -0400 Received: from mail-qt0-f193.google.com ([209.85.216.193]:36542 "EHLO mail-qt0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726974AbeHaIGU (ORCPT ); Fri, 31 Aug 2018 04:06:20 -0400 Received: by mail-qt0-f193.google.com with SMTP id t5-v6so13211524qtn.3 for ; Thu, 30 Aug 2018 21:00:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=b64P0+MjWitzIAScjIg7tmBdces6Djffht8rg+7UQcs=; b=iBflPakWyxKXv0f+eUfNy6wPdE7j/hakwwyL/mQHK3KAIhyJeuXF5WKA/yJ6ENFsW5 KswFD4e3LWZQdpONIjL5UEf3Re0HfNi2letxpzRDr7lC9/y5V9TODSwcTWk7IjdUnju1 z4TRLha+ZAtgcgFU3VOFbe3yTw6kEXd3W/hXlWGxx1ezpnLh1OLNYMH5jH9PCJlIRjaN ZIoJH6RA4SgMbnY7uyynWw9a84HhbaKCO8nrOhWHL2WXUnSipo7OSj7PT92YSZXiE/P7 6UIB8MoF2525HUi5pQ8y7N1monCXE4kZWB2EnzbaYo+BD4Q9hjxLFC1jKmxfe4MswYCY LDBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=b64P0+MjWitzIAScjIg7tmBdces6Djffht8rg+7UQcs=; b=C3H2CoZ3WiRkuI3Z/SsNsKS9wPNoP8UbLE/YQ3ORCq3PB2GMwBPrXF0KamN/wovRVF M9Z9vRbTF53tq+9z6ML3f0jYaid9Wemb1h8wam0VfUDsgaAU//nXAsrXjKHod09258yj sAV1H3P/XwE5nK5TFRWjfJ0JqBGIiGXjBcBXn1nXxjKTdRiO9GCJGRHy3YhuDfljwq9t t2z0XUtXiKLEk6fPugq0L17smCs7Iy/xiLskpDfliHkBVAJx7U8PTYDsCdfJsypEangp Bw9yqFpOMb8x4+lKwj5aG18nPIOHk2BZmMVq7I/MUfNe8FvXb+NCXDXHl1Ihc9bQ0taO 8twA== X-Gm-Message-State: APzg51AmnsCYXc/8okNl6lqAOAVUUERF4kRIU9crMmwu9DnpmbCXlBNX ez1EwYFOPYJjgrx6ticpk6GJjpF4 X-Google-Smtp-Source: ANB0VdYLqfn/B8wIL0kMqk34iFKQ4VhQc3T37/zchah16HRjMcESfvWbQSzRjUxZcj6s3Y00UKzbgg== X-Received: by 2002:ac8:41d1:: with SMTP id o17-v6mr14720617qtm.265.1535688054783; Thu, 30 Aug 2018 21:00:54 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id p57-v6sm5730197qtj.42.2018.08.30.21.00.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Aug 2018 21:00:54 -0700 (PDT) Date: Fri, 31 Aug 2018 01:00:50 -0300 From: Ernesto =?utf-8?q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton Subject: [PATCH 4/6] hfs: prevent btree data loss on root split Message-ID: <9750b1415685c4adca10766895f6d5ef12babdb0.1535682463.git.ernesto.mnd.fernandez@gmail.com> References: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This bug is triggered whenever hfs_brec_update_parent() needs to split the root node. The height of the btree is not increased, which leaves the new node orphaned and its records lost. It is not possible for this to happen on a valid hfs filesystem because the index nodes have fixed length keys. For reasons I ignore, the hfs module does have support for a number of hfsplus features. A corrupt btree header may report variable length keys and trigger this bug, so it's better to fix it. Signed-off-by: Ernesto A. Fernández --- fs/hfs/brec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c index 9a8772465a90..da25c49203cc 100644 --- a/fs/hfs/brec.c +++ b/fs/hfs/brec.c @@ -425,6 +425,10 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) if (new_node) { __be32 cnid; + if (!new_node->parent) { + hfs_btree_inc_height(tree); + new_node->parent = tree->root; + } fd->bnode = hfs_bnode_find(tree, new_node->parent); /* create index key and entry */ hfs_bnode_read_key(new_node, fd->search_key, 14); From patchwork Fri Aug 31 04:01:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ernesto_A=2E_Fern=C3=A1ndez?= X-Patchwork-Id: 10583091 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C8F2F14BD for ; Fri, 31 Aug 2018 04:01:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B7E072BD94 for ; Fri, 31 Aug 2018 04:01:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AAD3F2BDC8; Fri, 31 Aug 2018 04:01:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 40CDD2BD94 for ; Fri, 31 Aug 2018 04:01:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727230AbeHaIGr (ORCPT ); Fri, 31 Aug 2018 04:06:47 -0400 Received: from mail-qt0-f196.google.com ([209.85.216.196]:41192 "EHLO mail-qt0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726974AbeHaIGr (ORCPT ); Fri, 31 Aug 2018 04:06:47 -0400 Received: by mail-qt0-f196.google.com with SMTP id t39-v6so13172024qtc.8 for ; Thu, 30 Aug 2018 21:01:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=USNwKbW2h88EaAAMZ27ksiiwdAnFgrhoUaKMPlmsriM=; b=Dw5zjve2YxPVKRlThBHOU5FIu2ixEoiSnVdN0kk+nOPDWk6DE+3LbNnZ4r3GAxmad0 1KOK00v+MCtyWAPYZ3YBV/edrq3OuJ7FHw9ZcHK/o7NJmURC3VM1bbmPcDez6ymYZTxI jNj46tf+1FpAJjTsL2X+1Zs1M6ew7tuorHAL6hcOpYEmxH3izbfMcECrUvmvaLnt6XK5 fFuBBbhYgPfSotHW0IpIZYqmPNytGlQOU8BU9t1Mmy5eqZghsNs0EZqewIXRQgtDwWjB qCJU68LhXaJ3PTwbOzP9J6usiFfvhWbHinPvv5Yn/JXWN7eQTh6GtWJ0XABBSu2KzSMG uljw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=USNwKbW2h88EaAAMZ27ksiiwdAnFgrhoUaKMPlmsriM=; b=oMYe0E+NDjns+Z5/Ox0tF4DTsevTh7zi3zgW5I1bbruLoXbheRQbJBJB/K5B0IOF2n 3lsvV/VE7dQtEDZqtY01GnSDO82YrhvJgepOfVRnuxZ0jhQ/UuDlM1q0A2s0DyDMYhqw Tq7cURggb/TEOGde3s2y1268pBRohRxGRa73J//4hL0sYyYU2OyiJdkGmSNQQSHA/+in x0TfS3rktE3t6mN4owSXMN8cjTBYq/5jAbt5lVW/ZaqjEZnqXcImtKnGLV6/ILZg2wqN sB3qjeWZHDl7MDDy+gYOJ1A184qe9j216oTE4McfymQoMBu6mad0oH8D32Vec1OKjHw1 ZG/Q== X-Gm-Message-State: APzg51AyEKzRtdjO4LGbqLqNyk5r+Z9TUs6RSleH0yQ4hnBUMLG5X+mi marB2dLvL/mZTmpTH7y6BPr1+0Jn X-Google-Smtp-Source: ANB0VdbBSr+7fjpu9D8M68RCKwGIXCj4HjxabmS8u7EJRIXjthX406U53uQxZYkV6BPY4LkGyi/yuQ== X-Received: by 2002:ac8:376c:: with SMTP id p41-v6mr14359980qtb.225.1535688081735; Thu, 30 Aug 2018 21:01:21 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id n41-v6sm5909217qtn.73.2018.08.30.21.01.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Aug 2018 21:01:21 -0700 (PDT) Date: Fri, 31 Aug 2018 01:01:17 -0300 From: Ernesto =?utf-8?q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton Subject: [PATCH 5/6] hfs: fix BUG on bnode parent update Message-ID: References: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP hfs_brec_update_parent() may hit BUG_ON() if the first record of both a leaf node and its parent are changed, and if this forces the parent to be split. It is not possible for this to happen on a valid hfs filesystem because the index nodes have fixed length keys. For reasons I ignore, the hfs module does have support for a number of hfsplus features. A corrupt btree header may report variable length keys and trigger this BUG, so it's better to fix it. Signed-off-by: Ernesto A. Fernández --- fs/hfs/brec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c index da25c49203cc..896396554bcc 100644 --- a/fs/hfs/brec.c +++ b/fs/hfs/brec.c @@ -445,6 +445,7 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) /* restore search_key */ hfs_bnode_read_key(node, fd->search_key, 14); } + new_node = NULL; } if (!rec && node->parent) From patchwork Fri Aug 31 04:01:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ernesto_A=2E_Fern=C3=A1ndez?= X-Patchwork-Id: 10583093 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8348B920 for ; Fri, 31 Aug 2018 04:01:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 721012BD95 for ; Fri, 31 Aug 2018 04:01:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 65EFE2BDEC; Fri, 31 Aug 2018 04:01:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D346D2BD95 for ; Fri, 31 Aug 2018 04:01:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727239AbeHaIHJ (ORCPT ); Fri, 31 Aug 2018 04:07:09 -0400 Received: from mail-qt0-f195.google.com ([209.85.216.195]:38000 "EHLO mail-qt0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726974AbeHaIHI (ORCPT ); Fri, 31 Aug 2018 04:07:08 -0400 Received: by mail-qt0-f195.google.com with SMTP id x7-v6so13199872qtk.5 for ; Thu, 30 Aug 2018 21:01:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=uCxZQHbtfRWejyWbI3AogNB5ehdp34OI41lAnmKjJkk=; b=WXSdv6gBL3XnVQYOY5Q0tcg/FGEMZOQHeFa0kY79XHgD12Hksx3pXnuIO6wz20JDYv VUgPkZPF0spGPtp5DA/eHXrANeVDuwrqCtQiJN6IJsViBz4zrvIdOe81bamNuFOTlm0m Sjeo35rvqvXNcvJX9H7t719sFPd+mUgf47GSPyVW2xuqIOINGb0QVk8it+OezmLxPTRu U/1S5kC4wY5zLaM1FXYf1qw+1Rk5QG5hwuOavvX0idtqqm9OOdF8NrIaJi5mCVEWeQH8 /zmpyQyUK9rf4dgh8TGZepXlSIbb/Z6y0QivMiDWQlqKla/KKzaeJZPG0v9MlLc6EThH yLuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=uCxZQHbtfRWejyWbI3AogNB5ehdp34OI41lAnmKjJkk=; b=cvjR0yciYvfJK3dt+kUvgyaOWnDIQQE6Vu33e333RDE/WLm7Rh+GpqgKNJokB0RlOp +C5KYNjoYhkq2aOE5rzXvy131Sp/EZ/jPDs20OKdxkrIuGJriIrDghkfsdYRFzyDk4lm hPt87M/wuiV8MyZ69+m5j5MTgpgQGJ1o5oXMjVD3L0WrXWHp1bVmfxgSIz0uBBZunawx Y86fvSAwKnWh1QyMEHImWYI/GlgMVi0IMEHq82jwQqyzQykrlarYfpXEw78Ip4BfKlBh L3G/Vrg3xt7Y8mTbSsw5PM+FH4xMXGU0yOZ0+FqfrUA7SP6HBTo42/+0VJ8i7iV9E3OH ECew== X-Gm-Message-State: APzg51D1NHpmuqCnNGwwZZGTyKQRX9NA1UYg81jwVtxxL1ycd6MAm7Pu 76gMmBt0Dc0kohZQcNCVSf7EqGDq X-Google-Smtp-Source: ANB0VdZIdlOX7fNc1u2WdOtR0+c7DFYywMc8UkvSeqGRqAC1DIoGFBF6r1Y7ieFInoHBG/2PPbmjvQ== X-Received: by 2002:a0c:b9a9:: with SMTP id v41-v6mr341396qvf.63.1535688102381; Thu, 30 Aug 2018 21:01:42 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id a17-v6sm4769904qkb.62.2018.08.30.21.01.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Aug 2018 21:01:41 -0700 (PDT) Date: Fri, 31 Aug 2018 01:01:38 -0300 From: Ernesto =?utf-8?q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton Subject: [PATCH 6/6] hfs: prevent btree data loss on ENOSPC Message-ID: <68e77996d38baf789e8dc108ca6d210c5987f2ea.1535682464.git.ernesto.mnd.fernandez@gmail.com> References: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <26d882184fc43043a810114258f45277752186c7.1535682461.git.ernesto.mnd.fernandez@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Inserting a new record in a btree may require splitting several of its nodes. If we hit ENOSPC halfway through, the new nodes will be left orphaned and their records will be lost. This could mean lost inodes or extents. From now on, check the available disk space before making any changes. This still leaves the potential problem of corruption on ENOMEM. There is no need to reserve space before deleting a catalog record, as we do for hfsplus. This difference is because hfs index nodes have fixed length keys. Signed-off-by: Ernesto A. Fernández --- fs/hfs/btree.c | 39 ++++++++++++++++++++++++--------------- fs/hfs/btree.h | 1 + fs/hfs/catalog.c | 16 ++++++++++++++++ fs/hfs/extent.c | 4 ++++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c index 374b5688e29e..66c9e7f7170c 100644 --- a/fs/hfs/btree.c +++ b/fs/hfs/btree.c @@ -220,25 +220,17 @@ static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx) return node; } -struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) +/* Make sure @tree has enough space for the @rsvd_nodes */ +int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes) { - struct hfs_bnode *node, *next_node; - struct page **pagep; - u32 nidx, idx; - unsigned off; - u16 off16; - u16 len; - u8 *data, byte, m; - int i; - - while (!tree->free_nodes) { - struct inode *inode = tree->inode; - u32 count; - int res; + struct inode *inode = tree->inode; + u32 count; + int res; + while (tree->free_nodes < rsvd_nodes) { res = hfs_extend_file(inode); if (res) - return ERR_PTR(res); + return res; HFS_I(inode)->phys_size = inode->i_size = (loff_t)HFS_I(inode)->alloc_blocks * HFS_SB(tree->sb)->alloc_blksz; @@ -249,6 +241,23 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) tree->free_nodes = count - tree->node_count; tree->node_count = count; } + return 0; +} + +struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) +{ + struct hfs_bnode *node, *next_node; + struct page **pagep; + u32 nidx, idx; + unsigned off; + u16 off16; + u16 len; + u8 *data, byte, m; + int i, res; + + res = hfs_bmap_reserve(tree, 1); + if (res) + return ERR_PTR(res); nidx = 0; node = hfs_bnode_find(tree, nidx); diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h index c8b252dbb26c..dcc2aab1b2c4 100644 --- a/fs/hfs/btree.h +++ b/fs/hfs/btree.h @@ -82,6 +82,7 @@ struct hfs_find_data { extern struct hfs_btree *hfs_btree_open(struct super_block *, u32, btree_keycmp); extern void hfs_btree_close(struct hfs_btree *); extern void hfs_btree_write(struct hfs_btree *); +extern int hfs_bmap_reserve(struct hfs_btree *, int); extern struct hfs_bnode * hfs_bmap_alloc(struct hfs_btree *); extern void hfs_bmap_free(struct hfs_bnode *node); diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index 8a66405b0f8b..d365bf0b8c77 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c @@ -97,6 +97,14 @@ int hfs_cat_create(u32 cnid, struct inode *dir, const struct qstr *str, struct i if (err) return err; + /* + * Fail early and avoid ENOSPC during the btree operations. We may + * have to split the root node at most once. + */ + err = hfs_bmap_reserve(fd.tree, 2 * fd.tree->depth); + if (err) + goto err2; + hfs_cat_build_key(sb, fd.search_key, cnid, NULL); entry_size = hfs_cat_build_thread(sb, &entry, S_ISDIR(inode->i_mode) ? HFS_CDR_THD : HFS_CDR_FTH, @@ -295,6 +303,14 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, const struct qstr *src_name, return err; dst_fd = src_fd; + /* + * Fail early and avoid ENOSPC during the btree operations. We may + * have to split the root node at most once. + */ + err = hfs_bmap_reserve(src_fd.tree, 2 * src_fd.tree->depth); + if (err) + goto out; + /* find the old dir entry and read the data */ hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name); err = hfs_brec_find(&src_fd); diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index 5d0182654580..0c638c612152 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -117,6 +117,10 @@ static int __hfs_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) if (HFS_I(inode)->flags & HFS_FLG_EXT_NEW) { if (res != -ENOENT) return res; + /* Fail early and avoid ENOSPC during the btree operation */ + res = hfs_bmap_reserve(fd->tree, fd->tree->depth + 1); + if (res) + return res; hfs_brec_insert(fd, HFS_I(inode)->cached_extents, sizeof(hfs_extent_rec)); HFS_I(inode)->flags &= ~(HFS_FLG_EXT_DIRTY|HFS_FLG_EXT_NEW); } else {