From patchwork Mon Jul 9 20:25:52 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: 10515685 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D228B6024A for ; Mon, 9 Jul 2018 20:26:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C1DB328D80 for ; Mon, 9 Jul 2018 20:26:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B5CBD28DE2; Mon, 9 Jul 2018 20:26:00 +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 2B54128D80 for ; Mon, 9 Jul 2018 20:26:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932947AbeGIUZ6 (ORCPT ); Mon, 9 Jul 2018 16:25:58 -0400 Received: from mail-qt0-f193.google.com ([209.85.216.193]:45082 "EHLO mail-qt0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932686AbeGIUZ5 (ORCPT ); Mon, 9 Jul 2018 16:25:57 -0400 Received: by mail-qt0-f193.google.com with SMTP id y5-v6so16498725qti.12 for ; Mon, 09 Jul 2018 13:25:57 -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=SrMDaXoYWyxSRssBs2hBOPfSP5FHojHbgu3kBcuqU7o=; b=EdZKgh0JhT8/k1B6RKcZgnVDsKNkp0HB+Ri4RTzkcmRNQB+pSOBQ3C2xvy+KquL/n4 7Cp/LRRcC9A+h65GIkO0Xwpk43Qmfb32qO96mM/PhKqehJu1q0uOMAeqLu/w34voNpLB /oeYIejMnGeIm7N0kWrtTspwf5WAVpApgLVj/6o09aZHW8Q6ELtoDUxKA1KPHuUVDbgB 33zqfF0DLJrjRe3gf1s0Htacmmn6+HIRiGjb/M1uubI/GC/e3BK2a8zHJ8OfrI8IjHHt gH4JzfY07VGUVTLochmBTVJMXK2EfOHfPKpyl6wnwY0L/AlXW5p9q/iGA3zHYlLJZ5K1 Zx0Q== 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=SrMDaXoYWyxSRssBs2hBOPfSP5FHojHbgu3kBcuqU7o=; b=YqEdcQf2IMj3NKjEv157dSaO1AgDGPXoLszsWgj7Cq+hRn/vDW8VPlJI9ElC0uAsHt j/aB5YEQkrzEPDIvwg6Z5+Ud3Rn7gWQnZ4Zz1OGR8+Hg4yu4No2A//7SQ/Wqt5ldzT5I Y/gLg+C6RsFv7eyelc+6QUIuf8vPcyOid+cajBdq47QnGFc8tTWgmH9ifNhCbF6y9BAi YTwGjbGHN3xew+9kKKhjx28BOxiNBgUwHbYrNSM4r0giDz6s2P77mEpnVi4coXQ1ulkJ hvnqrFzUMyRpXNLeksQZLt/dAq/3QQdUrSsYUB3o4edDBVUXPb01sf9Zja33iw9NMZ4a ifCg== X-Gm-Message-State: APt69E2rQ2oLzQ8jhsXS1deZ/qHt7PbcLXLznK4BjXXotTC6tFXif3eN hwJNBhQCO37ECDnfg0Zw/joMEg== X-Google-Smtp-Source: AAOMgpfLcFVu1QdWJzUv0NhJrzapR7LnCsPLYQivwZo6ZGufqi/vp2+9bDsJ64nU8sEYi1yszHlepg== X-Received: by 2002:a0c:d8e8:: with SMTP id w37-v6mr18809601qvj.111.1531167957089; Mon, 09 Jul 2018 13:25:57 -0700 (PDT) Received: from eaf ([181.47.179.0]) by smtp.gmail.com with ESMTPSA id c93-v6sm16129522qkh.90.2018.07.09.13.25.55 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 09 Jul 2018 13:25:56 -0700 (PDT) Date: Mon, 9 Jul 2018 17:25:52 -0300 From: Ernesto =?utf-8?Q?A=2E_Fern=C3=A1ndez?= To: linux-fsdevel@vger.kernel.org Cc: Andrew Morton , Anatoly Trosinenko Subject: [PATCH] hfsplus: avoid deadlock on file truncation Message-ID: <20180709202549.auxwkb6memlegb4a@eaf> 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 After an extent is removed from the extent tree, the corresponding bits are also cleared from the block allocation file. This is currently done without releasing the tree lock. The problem is that the allocation file has extents of its own; if it is fragmented enough, some of them may be in the extent tree as well, and hfsplus_get_block() will try to take the lock again. To avoid deadlock, only hold the extent tree lock during the actual tree operations. Reported-by: Anatoly Trosinenko Signed-off-by: Ernesto A. Fernández --- fs/hfsplus/extents.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index e8770935ce6d..8e0f59767694 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -336,6 +336,9 @@ static int hfsplus_free_extents(struct super_block *sb, int i; int err = 0; + /* Mapping the allocation file may lock the extent tree */ + WARN_ON(mutex_is_locked(&HFSPLUS_SB(sb)->ext_tree->tree_lock)); + hfsplus_dump_extent(extent); for (i = 0; i < 8; extent++, i++) { count = be32_to_cpu(extent->block_count); @@ -415,11 +418,13 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, if (res) break; start = be32_to_cpu(fd.key->ext.start_block); - hfsplus_free_extents(sb, ext_entry, - total_blocks - start, - total_blocks); hfs_brec_remove(&fd); + + mutex_unlock(&fd.tree->tree_lock); + hfsplus_free_extents(sb, ext_entry, total_blocks - start, + total_blocks); total_blocks = start; + mutex_lock(&fd.tree->tree_lock); } while (total_blocks > blocks); hfs_find_exit(&fd); @@ -576,15 +581,20 @@ void hfsplus_file_truncate(struct inode *inode) } while (1) { if (alloc_cnt == hip->first_blocks) { + mutex_unlock(&fd.tree->tree_lock); hfsplus_free_extents(sb, hip->first_extents, alloc_cnt, alloc_cnt - blk_cnt); hfsplus_dump_extent(hip->first_extents); hip->first_blocks = blk_cnt; + mutex_lock(&fd.tree->tree_lock); break; } res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); if (res) break; + hfs_brec_remove(&fd); + + mutex_unlock(&fd.tree->tree_lock); start = hip->cached_start; hfsplus_free_extents(sb, hip->cached_extents, alloc_cnt - start, alloc_cnt - blk_cnt); @@ -596,7 +606,7 @@ void hfsplus_file_truncate(struct inode *inode) alloc_cnt = start; hip->cached_start = hip->cached_blocks = 0; hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW); - hfs_brec_remove(&fd); + mutex_lock(&fd.tree->tree_lock); } hfs_find_exit(&fd);