From patchwork Fri Apr 3 23:36:11 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Justin Maggard X-Patchwork-Id: 6160471 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 740AABF4A6 for ; Fri, 3 Apr 2015 23:36:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7E79C20396 for ; Fri, 3 Apr 2015 23:36:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6D34F2038A for ; Fri, 3 Apr 2015 23:36:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752057AbbDCXgO (ORCPT ); Fri, 3 Apr 2015 19:36:14 -0400 Received: from mail-wg0-f44.google.com ([74.125.82.44]:34296 "EHLO mail-wg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751032AbbDCXgN convert rfc822-to-8bit (ORCPT ); Fri, 3 Apr 2015 19:36:13 -0400 Received: by wgbdm7 with SMTP id dm7so121179348wgb.1 for ; Fri, 03 Apr 2015 16:36:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type :content-transfer-encoding; bh=e/wcb6/QI5EgPA2P/cq5vRK7iXb18F08xcCSz0tb1tc=; b=bRAGOzMYg0vZ+H1HswoKDJUrhX6hOmyX92XMegSytFAVGtip3NySoFCuD6G/Jidin9 wueqeEJG2paL3oOHaAjhB8dmnEqQ+P5NeYa/3F60KAuU95dn4658+naXKw288X4yJ/Ca XdDS2AlZ5XY3abLtBKMykrfTdq2NE+OzeGd3nLamIANYMhnQtShYJ/lyNG0MlXiEb3sH +8K/kwT1yfICKr8ZS7FXXqiMLZ9oebxgWRiC7pinTrYFt9rlx0Z92v9KLkTw95+Zhd6U dtwGF5QXNJNdzVnsLzA+CtQHVgDVpHPVU4g1AKP2ew89h1eFzFE0M7xdAVucgdLpuTXY Ze3w== MIME-Version: 1.0 X-Received: by 10.194.94.1 with SMTP id cy1mr9025441wjb.127.1428104171982; Fri, 03 Apr 2015 16:36:11 -0700 (PDT) Received: by 10.28.62.83 with HTTP; Fri, 3 Apr 2015 16:36:11 -0700 (PDT) Date: Fri, 3 Apr 2015 16:36:11 -0700 Message-ID: Subject: Btrfs ENOSPC issue From: Justin Maggard To: linux-btrfs@vger.kernel.org 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_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 Hi, We're hitting a consistently reproducible ENOSPC condition with a simple test case: # truncate -s 1T btrfs.fs # mkfs.btrfs btrfs.fs # mount btrfs.fs /mnt/ # fallocate -l 1021G /mnt/fallocate # btrfs fi sync /mnt/ # dd if=/dev/zero of=/mnt/dd bs=1G # btrfs fi sync /mnt/ # rm /mnt/fallocate # btrfs fi sync /mnt/ # fallocate -l 20G /mnt/fallocate fallocate: /mnt/fallocate: fallocate failed: No space left on device I continue to get ENOSPC even after unmount / mount. Here we have 1022GB free as reported by df, yet we can't allocate 20GB. I tried the integration-4.1 tree, which had the same results. I also added Zhao Lei's ENOSPC most recent patchset from today, but it didn't seem to help. So it appears that when allocating the first chunk, find_free_dev_extent() finds a huge hole, and allocates a portion of that free 1022GB. Real chunk allocation is delayed until transaction submit and does not insert the DEV_EXTENT item into the device tree immediately, so transaction->pending_chunks is used to record pending chunks. When it comes to the next chunk allocation, find_free_dev_extent() detects the same huge hole, but contains_pending_extent() returns true and sets hole_size to 0. This means we skip our one and only huge free space hole and try to search for some other free space holes. The problem occurs when there is not enough space for chunk allocation if we skip that huge hole, and find_free_dev_extent() eventually returns –ENOSPC. The following patch makes it work for me, but I certainly may have missed some subtleties in how btrfs allocation works; so if something is incorrect here, I'd appreciate feedback. If this is the proper way to go about fixing it, I can whip up a proper patch and post it to the list. Thanks, -Justin --- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a73acf4..d056448 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1053,7 +1053,7 @@ out: static int contains_pending_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, - u64 *start, u64 len) + u64 *start, u64 *len) { struct extent_map *em; struct list_head *search_list = &trans->transaction->pending_chunks; @@ -1068,12 +1068,16 @@ again: for (i = 0; i < map->num_stripes; i++) { if (map->stripes[i].dev != device) continue; - if (map->stripes[i].physical >= *start + len || + if (map->stripes[i].physical >= *start + *len || map->stripes[i].physical + em->orig_block_len <= *start) continue; *start = map->stripes[i].physical + em->orig_block_len; + if (*len > em->orig_block_len) + *len -= em->orig_block_len; + else + *len = 0; ret = 1; } } @@ -1191,10 +1195,9 @@ again: * Have to check before we set max_hole_start, otherwise * we could end up sending back this offset anyway. */ - if (contains_pending_extent(trans, device, - &search_start, - hole_size)) - hole_size = 0; + contains_pending_extent(trans, device, + &search_start, + &hole_size); if (hole_size > max_hole_size) { max_hole_start = search_start; @@ -1239,7 +1242,7 @@ next: max_hole_size = hole_size; } - if (contains_pending_extent(trans, device, &search_start, hole_size)) { + if (contains_pending_extent(trans, device, &search_start, &hole_size)) { btrfs_release_path(path); goto again; }