From patchwork Mon Mar 16 20:30:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 6025221 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8EA5FBF90F for ; Mon, 16 Mar 2015 20:31:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7722320340 for ; Mon, 16 Mar 2015 20:31:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 701572037A for ; Mon, 16 Mar 2015 20:31:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933359AbbCPUa7 (ORCPT ); Mon, 16 Mar 2015 16:30:59 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:16816 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933155AbbCPUaz (ORCPT ); Mon, 16 Mar 2015 16:30:55 -0400 Received: from pps.filterd (m0004077 [127.0.0.1]) by mx0b-00082601.pphosted.com (8.14.5/8.14.5) with SMTP id t2GKRXvl017229 for ; Mon, 16 Mar 2015 13:30:54 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=fb.com; h=from : to : subject : date : message-id : mime-version : content-type; s=facebook; bh=s2K2mc0sGV/XEZILBoosBl0Hpac8TnUpdqe7NAGKbRA=; b=HgA9GtZKpscn/UcU/c7ppFSh3BS6fSob/DXoJ5u3ZBhs+JVSN25iOfMF3MGQZkxnDBeD okbC/7C87XChHJ8hLu18lv1EOLEPesb7nyD42wvWakVa66Gkm18vbj+QzFucE62s+nOO E8qHjU4/PmyrMyezPOwJz+iqyUQZXS6uuPI= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0b-00082601.pphosted.com with ESMTP id 1t65a1g8fv-2 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT) for ; Mon, 16 Mar 2015 13:30:54 -0700 Received: from localhost (192.168.52.13) by mail.TheFacebook.com (192.168.16.17) with Microsoft SMTP Server (TLS) id 14.3.195.1; Mon, 16 Mar 2015 13:30:52 -0700 From: Josef Bacik To: Subject: [PATCH] Btrfs: fix merge delalloc logic V2 Date: Mon, 16 Mar 2015 16:30:50 -0400 Message-ID: <1426537850-24861-1-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 1.9.3 MIME-Version: 1.0 X-Originating-IP: [192.168.52.13] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.13.68, 1.0.33, 0.0.0000 definitions=2015-03-16_04:2015-03-16, 2015-03-16, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 kscore.is_bulkscore=5.18807219407336e-13 kscore.compositescore=0 circleOfTrustscore=0 compositescore=0.996183534634169 suspectscore=1 recipient_domain_to_sender_totalscore=0 phishscore=0 bulkscore=0 kscore.is_spamscore=0 rbsscore=0.996183534634169 recipient_to_sender_totalscore=0 recipient_domain_to_sender_domain_totalscore=0 spamscore=0 recipient_to_sender_domain_totalscore=0 urlsuspectscore=0.996183534634169 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1402240000 definitions=main-1503160206 X-FB-Internal: deliver Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP My patch to properly count outstanding extents wrt MAX_EXTENT_SIZE introduced a regression when joining two large areas. We need to take into account both sides of the merge to figure out if we're good with our current outstanding_extents count or if we need to drop it. For example if you merge two slightly larger than MAX_EXTENT size extents the accounting would incorrectly think we needed 4 outstanding extents when in fact we'd only need 3. Thanks, Reported-by: Markus Trippelsdorf Signed-off-by: Josef Bacik --- V1->V2: fixed another corner case where we join two large ranges fs/btrfs/inode.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 91a87f5..af4a492 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1591,8 +1591,10 @@ static void btrfs_merge_extent_hook(struct inode *inode, if (!(other->state & EXTENT_DELALLOC)) return; - old_size = other->end - other->start + 1; - new_size = old_size + (new->end - new->start + 1); + if (new->start > other->start) + new_size = new->end - other->start + 1; + else + new_size = other->end - new->start + 1; /* we're not bigger than the max, unreserve the space and go */ if (new_size <= BTRFS_MAX_EXTENT_SIZE) { @@ -1603,13 +1605,32 @@ static void btrfs_merge_extent_hook(struct inode *inode, } /* - * If we grew by another max_extent, just return, we want to keep that - * reserved amount. + * We have to add up either side to figure out how many extents were + * accounted for before we merged into one big extent. If the number of + * extents we accounted for is <= the amount we need for the new range + * then we can return, otherwise drop. Think of it like this + * + * [ 4k][MAX_SIZE] + * + * So we've grown the extent by a MAX_SIZE extent, this would mean we + * need 2 outstanding extents, on one side we have 1 and the other side + * we have 1 so they are == and we can return. But in this case + * + * [MAX_SIZE+4k][MAX_SIZE+4k] + * + * Each range on their own accounts for 2 extents, but merged together + * they are only 3 extents worth of accounting, so we need to drop in + * this case. */ + old_size = other->end - other->start + 1; num_extents = div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1, BTRFS_MAX_EXTENT_SIZE); + old_size = new->end - new->start + 1; + num_extents += div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1, + BTRFS_MAX_EXTENT_SIZE); + if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1, - BTRFS_MAX_EXTENT_SIZE) > num_extents) + BTRFS_MAX_EXTENT_SIZE) >= num_extents) return; spin_lock(&BTRFS_I(inode)->lock);