From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE735C33CB7 for ; Fri, 31 Jan 2020 22:36:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AA70220705 for ; Fri, 31 Jan 2020 22:36:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20150623.gappssmtp.com header.i=@toxicpanda-com.20150623.gappssmtp.com header.b="oLZBlIsA" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726907AbgAaWgp (ORCPT ); Fri, 31 Jan 2020 17:36:45 -0500 Received: from mail-qk1-f194.google.com ([209.85.222.194]:37494 "EHLO mail-qk1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726885AbgAaWgn (ORCPT ); Fri, 31 Jan 2020 17:36:43 -0500 Received: by mail-qk1-f194.google.com with SMTP id 21so8242715qky.4 for ; Fri, 31 Jan 2020 14:36:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=p3zRGXxK8EZ0Bwaao4g3Hwd+cSIC6ePOzvPRwrer+MY=; b=oLZBlIsAXSah9bs4xPBNt73INlS4D+BlAxMHf1ivtNcEBKXIzY95KUwf5ND/vlHsc6 K+p87Zz2wVsYqiEecJWOZgWsAQXC2fQbNZt4zDYILlmVWTj1KeZChWcEDvQhP2qPzxxv et5dpDsWtZQ6cbWg9fs3djDRQhnAnCiyP2YQII79o6dNfy/YiCxEXv7NTXon7SeS6HK1 XzRNZelaoiQeCkQxv9saPZpfbMql4kSdx5O3W7YoBAh3x4qif0c2txx1iKg7eB7F2EgF w7keWx2WWeIyITRzloFCE+82NwpmOtOMSeonJuH3J2AeK0k7pPx1Py9SZJQtwVnZ6AGq U+qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=p3zRGXxK8EZ0Bwaao4g3Hwd+cSIC6ePOzvPRwrer+MY=; b=kX2PVcXwhYqqD0Eo1UgGWVqWJRovTJH7WW6/vtb5TmMzgJg+dIT2hvyQbVykOV537K LvodPhwtrisZd0eAttdM4vDgAjhDhr7Mbd2Zx47wSduk9C2S592KgsjCPiUu38wTK30A 5Byrsy4evllJxG05A0ADCRACwRl1I2J1MXnjtvbW2Qeh9k0eHwdmXb6JqsAFVBwzcIWY kYxbf9pwkKxiwShZOUNTY87m0agQiSXuU67Pf+qaMrCgfJEwtat1Fq6w8v19mursm0Ns WlUT53b/ksBW3Nai3j02azK6psExk4BlQLjxazx2vdQ4O+Kr+bWKNxiZKn3TXj7hyJu9 f9TQ== X-Gm-Message-State: APjAAAW5oj1cxY5P7UibmS6zfKdBYrTmIbFopluaiwmrLO2vPpR8D3Fi O50NCJfGZLO4NGdqOeRLF8GgP0SAUM94Sw== X-Google-Smtp-Source: APXvYqzqE+W3dVLLXGbs0OgG8yf9n07GOsZE8pQmlXQYPToola+wyzAh74ii/R/0lbp2s5hBNoJuig== X-Received: by 2002:a37:2e82:: with SMTP id u124mr12584944qkh.294.1580510202361; Fri, 31 Jan 2020 14:36:42 -0800 (PST) Received: from localhost ([107.15.81.208]) by smtp.gmail.com with ESMTPSA id 205sm362457qkd.61.2020.01.31.14.36.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Jan 2020 14:36:41 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 15/23] btrfs: use ticketing for data space reservations Date: Fri, 31 Jan 2020 17:36:05 -0500 Message-Id: <20200131223613.490779-16-josef@toxicpanda.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200131223613.490779-1-josef@toxicpanda.com> References: <20200131223613.490779-1-josef@toxicpanda.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Now that we have all the infrastructure in place, use the ticketing infrastructure to make data allocations. This still maintains the exact same flushing behavior, but now we're using tickets to get our reservations satisfied. Signed-off-by: Josef Bacik --- fs/btrfs/space-info.c | 128 ++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 6b71f6d3a348..43c5775bcbc6 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -829,7 +829,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, int states_nr) { u64 to_reclaim; - int flush_state; + int flush_state = 0; spin_lock(&space_info->lock); to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info); @@ -839,7 +839,6 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, } spin_unlock(&space_info->lock); - flush_state = 0; do { flush_space(fs_info, space_info, to_reclaim, states[flush_state]); flush_state++; @@ -852,6 +851,54 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, } while (flush_state < states_nr); } +static void priority_reclaim_data_space(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, + struct reserve_ticket *ticket, + const enum btrfs_flush_state *states, + int states_nr) +{ + int flush_state = 0; + int commit_cycles = 2; + + while (!space_info->full) { + flush_space(fs_info, space_info, U64_MAX, ALLOC_CHUNK_FORCE); + spin_lock(&space_info->lock); + if (ticket->bytes == 0) { + spin_unlock(&space_info->lock); + return; + } + spin_unlock(&space_info->lock); + } +again: + while (flush_state < states_nr) { + u64 flush_bytes = U64_MAX; + + if (!commit_cycles) { + if (states[flush_state] == FLUSH_DELALLOC_WAIT) { + flush_state++; + continue; + } + if (states[flush_state] == COMMIT_TRANS) + flush_bytes = ticket->bytes; + } + + flush_space(fs_info, space_info, flush_bytes, + states[flush_state]); + spin_lock(&space_info->lock); + if (ticket->bytes == 0) { + spin_unlock(&space_info->lock); + return; + } + spin_unlock(&space_info->lock); + flush_state++; + } + if (commit_cycles) { + commit_cycles--; + flush_state = 0; + goto again; + } +} + static void wait_reserve_ticket(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, struct reserve_ticket *ticket) @@ -917,6 +964,15 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, evict_flush_states, ARRAY_SIZE(evict_flush_states)); break; + case BTRFS_RESERVE_FLUSH_DATA: + priority_reclaim_data_space(fs_info, space_info, ticket, + data_flush_states, + ARRAY_SIZE(data_flush_states)); + break; + case BTRFS_RESERVE_FLUSH_FREE_SPACE_INODE: + priority_reclaim_data_space(fs_info, space_info, ticket, + NULL, 0); + break; default: ASSERT(0); break; @@ -1096,78 +1152,30 @@ int btrfs_reserve_data_bytes(struct btrfs_fs_info *fs_info, u64 bytes, enum btrfs_reserve_flush_enum flush) { struct btrfs_space_info *data_sinfo = fs_info->data_sinfo; - const enum btrfs_flush_state *states = NULL; u64 used; - int states_nr = 0; - int commit_cycles = 2; int ret = -ENOSPC; ASSERT(!current->journal_info || flush != BTRFS_RESERVE_FLUSH_DATA); - if (flush == BTRFS_RESERVE_FLUSH_DATA) { - states = data_flush_states; - states_nr = ARRAY_SIZE(data_flush_states); - } - spin_lock(&data_sinfo->lock); -again: used = btrfs_space_info_used(data_sinfo, true); if (used + bytes > data_sinfo->total_bytes) { - u64 prev_total_bytes = data_sinfo->total_bytes; - int flush_state = 0; + struct reserve_ticket ticket; + init_waitqueue_head(&ticket.wait); + ticket.bytes = bytes; + ticket.error = 0; + list_add_tail(&ticket.list, &data_sinfo->priority_tickets); spin_unlock(&data_sinfo->lock); - /* - * Everybody can force chunk allocation, so try this first to - * see if we can just bail here and make our reservation. - */ - flush_space(fs_info, data_sinfo, bytes, ALLOC_CHUNK_FORCE); - spin_lock(&data_sinfo->lock); - if (prev_total_bytes < data_sinfo->total_bytes) - goto again; + ret = handle_reserve_ticket(fs_info, data_sinfo, &ticket, + flush); + } else { + btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); + ret = 0; spin_unlock(&data_sinfo->lock); - - /* - * Cycle through the rest of the flushing options for our flush - * type, then try again. - */ - while (flush_state < states_nr) { - u64 flush_bytes = U64_MAX; - - /* - * Previously we unconditionally committed the - * transaction twice before finally checking against - * pinned space before committing the final time. We - * also skipped flushing delalloc the final pass - * through. - */ - if (!commit_cycles) { - if (states[flush_state] == FLUSH_DELALLOC_WAIT) { - flush_state++; - continue; - } - if (states[flush_state] == COMMIT_TRANS) - flush_bytes = bytes; - } - - flush_space(fs_info, data_sinfo, flush_bytes, - states[flush_state]); - flush_state++; - } - - if (!commit_cycles) - goto out; - - commit_cycles--; - spin_lock(&data_sinfo->lock); - goto again; } - btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); - ret = 0; - spin_unlock(&data_sinfo->lock); -out: if (ret) trace_btrfs_space_reservation(fs_info, "space_info:enospc", -- 2.24.1