From patchwork Wed Apr 14 19:52:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gao Xiang X-Patchwork-Id: 12203673 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=-18.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, 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 C5493C433ED for ; Wed, 14 Apr 2021 19:53:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A6CD161154 for ; Wed, 14 Apr 2021 19:53:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353530AbhDNTxs (ORCPT ); Wed, 14 Apr 2021 15:53:48 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:26563 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353523AbhDNTxq (ORCPT ); Wed, 14 Apr 2021 15:53:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618430004; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=F9xF0hKxvdqIem8ylA2t9fMPF2dO98TC2hQY/cJildg=; b=HEgc9fXg2kDeKpvgnoq+7diumCXqVceZBRpFkFbqPx9SHLMxulJ3ENOBMU+hSkQ6ioyMgs U71Cnbi8pCtH/cwmw7fGMMJSdhnj1LlfFcRoIWYOZ9TRVGB7OP4BTGRIbEKbMJDeIUX+qT ucj6AjRPNbAGiHokNdRsALptiXKkPII= Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-519-MFkaj0-wM7q4XZ_auy2NzQ-1; Wed, 14 Apr 2021 15:53:23 -0400 X-MC-Unique: MFkaj0-wM7q4XZ_auy2NzQ-1 Received: by mail-pl1-f197.google.com with SMTP id d29-20020a17090259ddb02900eadb61377aso6563321plj.22 for ; Wed, 14 Apr 2021 12:53:23 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=F9xF0hKxvdqIem8ylA2t9fMPF2dO98TC2hQY/cJildg=; b=r3vx6CO//gYJZ/X0H9h1i+gKnqiCCRp8iWIm+pQvg45McQHrnV+sD6Mukzb83VBfom UR5s/JRxnYW0K7G7WeQqMtMCg426vqWlyTo8hqF+2mesGseXugc735mBvUnCXuf0DAxo Fk/qN7lRFsj9IRiPpOTC6H/hCI2MQKYfpAmcJRPHwCKQOtrmhovyh9kh4nO2IaORAPhQ 4knOkE7W2aaP/scVUazFLWJw79dO1RmHeP1o/vtKxWcz9V+EbV06rO2KsJIUfRlv7HNr w0U5Jf7D2NAQ1UtYc9nzcMrSpDo9G7IfNMYn1qdMalZ3uTjTVlN0kXdPjWbGm1TA4srF qeHQ== X-Gm-Message-State: AOAM530AhktU/YhoPw3is2lKmFkaWMRZnttnzbP33v/HE3Lx+pSRnAsx TZlqPS/6DoDHHfCXh7OttDFugne/nzYdEsB/ApX37vxkMOj4I5biadRwL59vtNddhDFUNnSNYrP zTuuL++FvNOrXxfDzXKij21akAG4zQJw6Zk5+2CTQqgoNxk8aYPuYdUX/zGcARZNwNkD0gSo8QQ == X-Received: by 2002:a62:2c46:0:b029:245:6391:b631 with SMTP id s67-20020a622c460000b02902456391b631mr29657730pfs.67.1618430001732; Wed, 14 Apr 2021 12:53:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwxAvF6Q7omURQ4Qi/zwLElUxw+jEN4YnLkkvNoEHoCSEEq9JRQd3vfiYIR4Ing5UcP0fJ1CQ== X-Received: by 2002:a62:2c46:0:b029:245:6391:b631 with SMTP id s67-20020a622c460000b02902456391b631mr29657707pfs.67.1618430001360; Wed, 14 Apr 2021 12:53:21 -0700 (PDT) Received: from xiangao.remote.csb ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id 11sm215787pjm.0.2021.04.14.12.53.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Apr 2021 12:53:21 -0700 (PDT) From: Gao Xiang To: linux-xfs@vger.kernel.org Cc: Gao Xiang Subject: [RFC PATCH 1/4] xfs: support deactivating AGs Date: Thu, 15 Apr 2021 03:52:37 +0800 Message-Id: <20210414195240.1802221-2-hsiangkao@redhat.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210414195240.1802221-1-hsiangkao@redhat.com> References: <20210414195240.1802221-1-hsiangkao@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org To get rid of paralleled requests related to AGs which are pending for shrinking, mark these perags as inactive rather than playing with per-ag structures theirselves. Since in that way, a per-ag lock can be used to stablize the inactive status together with agi/agf buffer lock (which is much easier than adding more complicated perag_{get, put} pairs..) Also, Such per-ags can be released / reused when unmountfs / growfs. On the read side, pag_inactive_rwsem can be unlocked immediately after the agf or agi buffer lock is acquired. However, pag_inactive_rwsem can only be unlocked after the agf/agi buffer locks are all acquired with the inactive status on the write side. XXX: maybe there are some missing cases. Signed-off-by: Gao Xiang --- fs/xfs/libxfs/xfs_ag.c | 16 +++++++++++++--- fs/xfs/libxfs/xfs_alloc.c | 12 +++++++++++- fs/xfs/libxfs/xfs_ialloc.c | 26 +++++++++++++++++++++++++- fs/xfs/xfs_mount.c | 2 ++ fs/xfs/xfs_mount.h | 6 ++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c index c68a36688474..ba5702e5c9ad 100644 --- a/fs/xfs/libxfs/xfs_ag.c +++ b/fs/xfs/libxfs/xfs_ag.c @@ -676,16 +676,24 @@ xfs_ag_get_geometry( if (agno >= mp->m_sb.sb_agcount) return -EINVAL; + pag = xfs_perag_get(mp, agno); + down_read(&pag->pag_inactive_rwsem); + + if (pag->pag_inactive) { + error = -EBUSY; + up_read(&pag->pag_inactive_rwsem); + goto out; + } + /* Lock the AG headers. */ error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp); + up_read(&pag->pag_inactive_rwsem); if (error) - return error; + goto out; error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp); if (error) goto out_agi; - pag = agi_bp->b_pag; - /* Fill out form. */ memset(ageo, 0, sizeof(*ageo)); ageo->ag_number = agno; @@ -707,5 +715,7 @@ xfs_ag_get_geometry( xfs_buf_relse(agf_bp); out_agi: xfs_buf_relse(agi_bp); +out: + xfs_perag_put(pag); return error; } diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index aaa19101bb2a..01d4e4d4c1d6 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2537,12 +2537,17 @@ xfs_alloc_fix_freelist( /* deferred ops (AGFL block frees) require permanent transactions */ ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); + down_read(&pag->pag_inactive_rwsem); + if (pag->pag_inactive) + goto out_no_agbp; + if (!pag->pagf_init) { error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); if (error) { /* Couldn't lock the AGF so skip this AG. */ if (error == -EAGAIN) error = 0; + up_read(&pag->pag_inactive_rwsem); goto out_no_agbp; } } @@ -2555,13 +2560,16 @@ xfs_alloc_fix_freelist( if (pag->pagf_metadata && (args->datatype & XFS_ALLOC_USERDATA) && (flags & XFS_ALLOC_FLAG_TRYLOCK)) { ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); + up_read(&pag->pag_inactive_rwsem); goto out_agbp_relse; } need = xfs_alloc_min_freelist(mp, pag); if (!xfs_alloc_space_available(args, need, flags | - XFS_ALLOC_FLAG_CHECK)) + XFS_ALLOC_FLAG_CHECK)) { + up_read(&pag->pag_inactive_rwsem); goto out_agbp_relse; + } /* * Get the a.g. freespace buffer. @@ -2573,9 +2581,11 @@ xfs_alloc_fix_freelist( /* Couldn't lock the AGF so skip this AG. */ if (error == -EAGAIN) error = 0; + up_read(&pag->pag_inactive_rwsem); goto out_no_agbp; } } + up_read(&pag->pag_inactive_rwsem); /* reset a padding mismatched agfl before final free space check */ if (pag->pagf_agflreset) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index eefdb518fe64..4df218eeb088 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -969,11 +969,15 @@ xfs_ialloc_ag_select( flags = XFS_ALLOC_FLAG_TRYLOCK; for (;;) { pag = xfs_perag_get(mp, agno); + down_read(&pag->pag_inactive_rwsem); if (!pag->pagi_inodeok) { xfs_ialloc_next_ag(mp); goto nextag; } + if (pag->pag_inactive) + goto nextag; + if (!pag->pagi_init) { error = xfs_ialloc_pagi_init(mp, tp, agno); if (error) @@ -981,6 +985,7 @@ xfs_ialloc_ag_select( } if (pag->pagi_freecount) { + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); return agno; } @@ -1016,10 +1021,12 @@ xfs_ialloc_ag_select( if (pag->pagf_freeblks >= needspace + ineed && longest >= ineed) { + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); return agno; } nextag: + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); /* * No point in iterating over the rest, if we're shutting @@ -1776,10 +1783,13 @@ xfs_dialloc_select_ag( agno = start_agno; for (;;) { pag = xfs_perag_get(mp, agno); + down_read(&pag->pag_inactive_rwsem); if (!pag->pagi_inodeok) { xfs_ialloc_next_ag(mp); goto nextag; } + if (pag->pag_inactive) + goto nextag; if (!pag->pagi_init) { error = xfs_ialloc_pagi_init(mp, *tpp, agno); @@ -1802,6 +1812,7 @@ xfs_dialloc_select_ag( break; if (pag->pagi_freecount) { + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); goto found_ag; } @@ -1825,6 +1836,7 @@ xfs_dialloc_select_ag( * allocate one of the new inodes. */ ASSERT(pag->pagi_freecount > 0); + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); error = xfs_dialloc_roll(tpp, agbp); @@ -1838,13 +1850,14 @@ xfs_dialloc_select_ag( nextag_relse_buffer: xfs_trans_brelse(*tpp, agbp); nextag: + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); if (++agno == mp->m_sb.sb_agcount) agno = 0; if (agno == start_agno) return noroom ? -ENOSPC : 0; } - + up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); return error; found_ag: @@ -2263,11 +2276,22 @@ xfs_imap_lookup( { struct xfs_inobt_rec_incore rec; struct xfs_btree_cur *cur; + struct xfs_perag *pag; struct xfs_buf *agbp; int error; int i; + pag = xfs_perag_get(mp, agno); + down_read(&pag->pag_inactive_rwsem); + if (pag->pag_inactive) { + up_read(&pag->pag_inactive_rwsem); + xfs_perag_put(pag); + return -EINVAL; + } + error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); + up_read(&pag->pag_inactive_rwsem); + xfs_perag_put(pag); if (error) { xfs_alert(mp, "%s: xfs_ialloc_read_agi() returned error %d, agno %d", diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 1c97b155a8ee..f86360514828 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -235,6 +235,8 @@ xfs_initialize_perag( if (error) goto out_hash_destroy; spin_lock_init(&pag->pag_state_lock); + + init_rwsem(&pag->pag_inactive_rwsem); } index = xfs_set_inode_alloc(mp, agcount); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 81829d19596e..667dae0acaf9 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -309,6 +309,12 @@ typedef struct xfs_perag { struct xfs_mount *pag_mount; /* owner filesystem */ xfs_agnumber_t pag_agno; /* AG this structure belongs to */ atomic_t pag_ref; /* perag reference count */ + + struct rw_semaphore pag_inactive_rwsem; + bool pag_inactive; + + /* zero the following fields when growfs pag_inactive == true pags */ + char pagf_init; /* this agf's entry is initialized */ char pagi_init; /* this agi's entry is initialized */ char pagf_metadata; /* the agf is preferred to be metadata */ From patchwork Wed Apr 14 19:52:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gao Xiang X-Patchwork-Id: 12203675 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=-18.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, 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 DBE98C433ED for ; Wed, 14 Apr 2021 19:53:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B5C3661153 for ; Wed, 14 Apr 2021 19:53:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353524AbhDNTxv (ORCPT ); Wed, 14 Apr 2021 15:53:51 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:29243 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353523AbhDNTxt (ORCPT ); Wed, 14 Apr 2021 15:53:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618430007; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qR6fSKF4jbqhXgpR/YinlnBP8rdJxsr6LZEc5Z+dtrY=; b=M5+RB83ClC8N++ad33+BvCGIDoTpgfmZeZyek0TqfAYoCGj/IkZvSe6o3kCzu2Ma44KVoT DxW1522w3vK9VLaQixrs6MmPJropcAe51+i4GvfZlgm7FZBY/oRgmpWTSQf3nCANww7ia6 zdRO2VTmZFBL3H8Qb0qB2deQkstS2pA= Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-45-e9EcgnYPM1uTEmvzi2xdNw-1; Wed, 14 Apr 2021 15:53:25 -0400 X-MC-Unique: e9EcgnYPM1uTEmvzi2xdNw-1 Received: by mail-pl1-f200.google.com with SMTP id v15-20020a170902d68fb02900e981de9bebso7500793ply.2 for ; Wed, 14 Apr 2021 12:53:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qR6fSKF4jbqhXgpR/YinlnBP8rdJxsr6LZEc5Z+dtrY=; b=qIdcLlmmvz0QKXc7gWJHrVWoa8GZpiy83bZlbZ1aUFUoeIdMqz/xcEX8S50b8fmOhZ MJ/jq24/Oxxsf/PLMLTp6BDYznDR5RyCPBXTHfc3uG2hg5wwFMsTTaGVJ5JsaWbetRB1 gsTH3rFSrTyH5ARAndrmikoqCgAdAIud4ATwlcpoXbSGYx4MQ35R6OFieS9q94MMmRJg RDe+PErfBsl1M4WJyykBvRPADAgCImOG0lKgusWlIFrp9nyxeD8mMGDzRX3FLc5fU/Bj VlSTR3WHI8f+yT9fdFPcvG7tuWksSCOD4eG0hL1fMvaiOC/cLIKHlBrRY/Udx8uHC91L Skdg== X-Gm-Message-State: AOAM533l57qXokomGoKHBBt+MoEG4oI8crPVPLIWkTSkAIOZgV+TRbFk Qtx6KCJNTZag5DWNHWPNPM3xrlKYWFNvM+gzdSrRvJrVtatl3/gKbK2klYj5A1K2IZ1h3qIBhfp nsWYymc1G0PN0MUiUO7Q8KL/yfkO+zix+kTnX7cwXsdiJBaldfXzi6HSRlYNdBWizbSGbHs2nTg == X-Received: by 2002:a17:90a:c209:: with SMTP id e9mr5352422pjt.104.1618430004537; Wed, 14 Apr 2021 12:53:24 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyEh/2amF+8rs/oiiL7UP2cXcIWu3u2+mPCzcyk+4AwCKxBKB/zrjZKAlyO/nJ6zdhqW2ak0w== X-Received: by 2002:a17:90a:c209:: with SMTP id e9mr5352408pjt.104.1618430004303; Wed, 14 Apr 2021 12:53:24 -0700 (PDT) Received: from xiangao.remote.csb ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id 11sm215787pjm.0.2021.04.14.12.53.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Apr 2021 12:53:24 -0700 (PDT) From: Gao Xiang To: linux-xfs@vger.kernel.org Cc: Gao Xiang Subject: [RFC PATCH 2/4] xfs: check ag is empty Date: Thu, 15 Apr 2021 03:52:38 +0800 Message-Id: <20210414195240.1802221-3-hsiangkao@redhat.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210414195240.1802221-1-hsiangkao@redhat.com> References: <20210414195240.1802221-1-hsiangkao@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org After a perag is stableized as inactive, we could check if such ag is empty. In order to achieve that, AGFL is also needed to be emptified in advance to make sure that only one freespace extent will exist here. Signed-off-by: Gao Xiang --- fs/xfs/libxfs/xfs_alloc.c | 97 +++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_alloc.h | 4 ++ 2 files changed, 101 insertions(+) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 01d4e4d4c1d6..60a8c134c00e 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2474,6 +2474,103 @@ xfs_defer_agfl_block( xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list); } +int +xfs_ag_emptify_agfl( + struct xfs_buf *agfbp) +{ + struct xfs_mount *mp = agfbp->b_mount; + struct xfs_perag *pag = agfbp->b_pag; + struct xfs_trans *tp; + int error; + struct xfs_owner_info oinfo = XFS_RMAP_OINFO_AG; + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata, 0, 0, + XFS_TRANS_RESERVE, &tp); + if (error) + return error; + + /* attach to the transaction and keep it from unlocked */ + xfs_trans_bjoin(tp, agfbp); + xfs_trans_bhold(tp, agfbp); + + while (pag->pagf_flcount) { + xfs_agblock_t bno; + int error; + + error = xfs_alloc_get_freelist(tp, agfbp, &bno, 0); + if (error) + break; + + ASSERT(bno != NULLAGBLOCK); + xfs_defer_agfl_block(tp, pag->pag_agno, bno, &oinfo); + } + xfs_trans_set_sync(tp); + xfs_trans_commit(tp); + return error; +} + +int +xfs_ag_is_empty( + struct xfs_buf *agfbp) +{ + struct xfs_mount *mp = agfbp->b_mount; + struct xfs_perag *pag = agfbp->b_pag; + struct xfs_agf *agf = agfbp->b_addr; + struct xfs_btree_cur *cnt_cur; + xfs_agblock_t nfbno; + xfs_extlen_t nflen; + int error, i; + + if (!pag->pag_inactive) + return -EINVAL; + + if (pag->pagf_freeblks + pag->pagf_flcount != + be32_to_cpu(agf->agf_length) - mp->m_ag_prealloc_blocks) + return -ENOTEMPTY; + + if (pag->pagf_flcount) { + error = xfs_ag_emptify_agfl(agfbp); + if (error) + return error; + + if (pag->pagf_freeblks != + be32_to_cpu(agf->agf_length) - mp->m_ag_prealloc_blocks) + return -ENOTEMPTY; + } + + if (pag->pagi_count > 0 || pag->pagi_freecount > 0) + return -ENOTEMPTY; + + if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > 1 || + be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > 1) + return -ENOTEMPTY; + + cnt_cur = xfs_allocbt_init_cursor(mp, NULL, agfbp, + pag->pag_agno, XFS_BTNUM_CNT); + ASSERT(cnt_cur->bc_nlevels == 1); + error = xfs_alloc_lookup_ge(cnt_cur, 0, + be32_to_cpu(agf->agf_longest), &i); + if (error || !i) + goto out; + + error = xfs_alloc_get_rec(cnt_cur, &nfbno, &nflen, &i); + if (error) + goto out; + + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out; + } + + error = -ENOTEMPTY; + if (nfbno == mp->m_ag_prealloc_blocks && + nflen == pag->pagf_freeblks) + error = 0; +out: + xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); + return error; +} + #ifdef DEBUG /* * Check if an AGF has a free extent record whose length is equal to diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index a4427c5775c2..a7015b971075 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -156,6 +156,10 @@ xfs_alloc_read_agf( int flags, /* XFS_ALLOC_FLAG_... */ struct xfs_buf **bpp); /* buffer for the ag freelist header */ +int +xfs_ag_is_empty( + struct xfs_buf *agfbp); + /* * Allocate an extent (variable-size). */ From patchwork Wed Apr 14 19:52:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gao Xiang X-Patchwork-Id: 12203677 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=-18.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, 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 04013C43460 for ; Wed, 14 Apr 2021 19:53:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CC15A61154 for ; Wed, 14 Apr 2021 19:53:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235073AbhDNTyG (ORCPT ); Wed, 14 Apr 2021 15:54:06 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:29264 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353548AbhDNTxw (ORCPT ); Wed, 14 Apr 2021 15:53:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618430010; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Gliz9OEP1Vaz9Jw809LedUaiNrGIv9h72Uhhip6g65A=; b=iV/LlVoR8bybbRsv+qIat2APQy0ixKsEBU9u5EqaY3B3jVAUASEGPxbMZ+sopUIjvAG5W2 XaYsyvGrKYP9thpV10YWtDQiWt7IlQLKrayE1GuSrvjmlraRFQLrjKUV/ueZ0vLH5lu0QO e9NYLMdw1Zd8FgQhDUeNviE794j2c8M= Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-331-lHG275mxMquc1l_4wlVdQQ-1; Wed, 14 Apr 2021 15:53:28 -0400 X-MC-Unique: lHG275mxMquc1l_4wlVdQQ-1 Received: by mail-pg1-f198.google.com with SMTP id w8-20020a6556c80000b02902072432fdabso114088pgs.21 for ; Wed, 14 Apr 2021 12:53:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Gliz9OEP1Vaz9Jw809LedUaiNrGIv9h72Uhhip6g65A=; b=b0h8gFkiNi15JWiqmEo2CDODGnqaR9gdzkWev5Pu/9nz+KhEacF46YbkLY7Tj5UFMm e8POqWtRZ5S5bmi9bMzYr3b4zvmVILZO0Tk9C40D47Ikue8+biWCgXYJdJ43P/5kIrra xeVL5xTcyPB8fZMeY5V+4zScKdSF+Ay+usaTZQyg0QYHNvWTwha0A1pMYqZYmMyLLY8x L31Hc8jjYtZb+QqDlNLaamREeZo++HpP1pD0W3I0w2W91rkYzZpPFbhAoK23MapTIJ4o gB340Jmn+FnbRSxt70SsJBwtYzvp6BCWnAjwY/aHF9J2Wq7GHsfEdgFVLCNjrP1wQFER 888w== X-Gm-Message-State: AOAM531lAF3Tp4qYKR4ZMWiNCHwsvNkCN1z9/6aie7MjvGgizGkX7wXH wtEmH+V+8BwurRnNv4JcANIwTzmItl4VdYfrUryP6cuB0BXrx1iFKyX2zxKYjVs+MNjw5xZLxR9 ZDktFg4OHTz4R1b9lbTldtmkXza47526qbQycGowyYf+0CNbeZ5iKegq4FQ9CkFlHB9Fa42Iozw == X-Received: by 2002:a63:ea06:: with SMTP id c6mr13852893pgi.401.1618430007415; Wed, 14 Apr 2021 12:53:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxqbTcd8hEICfM5Nd9drlvTOnTiqTHMmwcy63XiMZXoQKExlF8XjsdvtsA3ejspU6CTFNicug== X-Received: by 2002:a63:ea06:: with SMTP id c6mr13852864pgi.401.1618430007069; Wed, 14 Apr 2021 12:53:27 -0700 (PDT) Received: from xiangao.remote.csb ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id 11sm215787pjm.0.2021.04.14.12.53.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Apr 2021 12:53:26 -0700 (PDT) From: Gao Xiang To: linux-xfs@vger.kernel.org Cc: Gao Xiang Subject: [RFC PATCH 3/4] xfs: introduce max_agcount Date: Thu, 15 Apr 2021 03:52:39 +0800 Message-Id: <20210414195240.1802221-4-hsiangkao@redhat.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210414195240.1802221-1-hsiangkao@redhat.com> References: <20210414195240.1802221-1-hsiangkao@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org After shrinking, some inactive AGs won't be valid anymore except that these perags are still here. Introduce a new m_maxagcount mainly used for freeing all perags. Signed-off-by: Gao Xiang --- fs/xfs/libxfs/xfs_alloc.c | 2 +- fs/xfs/libxfs/xfs_bmap.c | 8 ++++---- fs/xfs/libxfs/xfs_ialloc.c | 2 +- fs/xfs/libxfs/xfs_sb.c | 1 + fs/xfs/xfs_extent_busy.c | 2 +- fs/xfs/xfs_mount.c | 4 ++-- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_trans.c | 2 ++ 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 60a8c134c00e..a493aaa955d7 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -3220,7 +3220,7 @@ xfs_alloc_vextent( args->maxlen = agsize; if (args->alignment == 0) args->alignment = 1; - ASSERT(XFS_FSB_TO_AGNO(mp, args->fsbno) < mp->m_sb.sb_agcount); + ASSERT(XFS_FSB_TO_AGNO(mp, args->fsbno) < mp->m_maxagcount); ASSERT(XFS_FSB_TO_AGBNO(mp, args->fsbno) < agsize); ASSERT(args->minlen <= args->maxlen); ASSERT(args->minlen <= agsize); diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 5574d345d066..abbb2a8aa0c0 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -350,7 +350,7 @@ xfs_bmap_check_leaf_extents( bno = be64_to_cpu(*pp); ASSERT(bno != NULLFSBLOCK); - ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); + ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_maxagcount); ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks); /* @@ -546,7 +546,7 @@ __xfs_bmap_add_free( ASSERT(!isnullstartblock(bno)); agno = XFS_FSB_TO_AGNO(mp, bno); agbno = XFS_FSB_TO_AGBNO(mp, bno); - ASSERT(agno < mp->m_sb.sb_agcount); + ASSERT(agno < mp->m_maxagcount); ASSERT(agbno < mp->m_sb.sb_agblocks); ASSERT(len < mp->m_sb.sb_agblocks); ASSERT(agbno + len <= mp->m_sb.sb_agblocks); @@ -3129,7 +3129,7 @@ xfs_bmap_adjacent( (rt ? \ (x) < mp->m_sb.sb_rblocks : \ XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \ - XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \ + XFS_FSB_TO_AGNO(mp, x) < mp->m_maxagcount && \ XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) mp = ap->ip->i_mount; @@ -3353,7 +3353,7 @@ xfs_bmap_btalloc_nullfb( if (error) return error; - if (++ag == mp->m_sb.sb_agcount) + if (++ag == mp->m_maxagcount) ag = 0; if (ag == startag) break; diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 4df218eeb088..2b80dcb428bf 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -1852,7 +1852,7 @@ xfs_dialloc_select_ag( nextag: up_read(&pag->pag_inactive_rwsem); xfs_perag_put(pag); - if (++agno == mp->m_sb.sb_agcount) + if (++agno == mp->m_maxagcount) agno = 0; if (agno == start_agno) return noroom ? -ENOSPC : 0; diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 60e6d255e5e2..6062b799d1e0 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -807,6 +807,7 @@ xfs_sb_mount_common( struct xfs_sb *sbp) { mp->m_agfrotor = mp->m_agirotor = 0; + mp->m_maxagcount = mp->m_sb.sb_agcount; mp->m_maxagi = mp->m_sb.sb_agcount; mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG; mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index ef17c1f6db32..b6d9d6e6da90 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -608,7 +608,7 @@ xfs_extent_busy_wait_all( DEFINE_WAIT (wait); xfs_agnumber_t agno; - for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + for (agno = 0; agno < mp->m_maxagcount; agno++) { struct xfs_perag *pag = xfs_perag_get(mp, agno); do { diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index f86360514828..69a60b5f4a32 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -141,7 +141,7 @@ xfs_free_perag( xfs_agnumber_t agno; struct xfs_perag *pag; - for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + for (agno = 0; agno < mp->m_maxagcount; agno++) { spin_lock(&mp->m_perag_lock); pag = radix_tree_delete(&mp->m_perag_tree, agno); spin_unlock(&mp->m_perag_lock); @@ -633,7 +633,7 @@ xfs_check_summary_counts( !xfs_fs_has_sickness(mp, XFS_SICK_FS_COUNTERS)) return 0; - return xfs_initialize_perag_data(mp, mp->m_sb.sb_agcount); + return xfs_initialize_perag_data(mp, mp->m_maxagcount); } /* diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 667dae0acaf9..6bc1cedd4cd5 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -192,6 +192,7 @@ typedef struct xfs_mount { */ struct work_struct m_flush_inodes_work; + xfs_agnumber_t m_maxagcount; /* * Generation of the filesysyem layout. This is incremented by each * growfs, and used by the pNFS server to ensure the client updates diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index bc25afc10245..1d37de86fc09 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -632,6 +632,8 @@ xfs_trans_unreserve_and_mod_sb( mp->m_sb.sb_frextents += rtxdelta; mp->m_sb.sb_dblocks += tp->t_dblocks_delta; mp->m_sb.sb_agcount += tp->t_agcount_delta; + if (mp->m_sb.sb_agcount > mp->m_maxagcount) + mp->m_maxagcount = mp->m_sb.sb_agcount; mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta; mp->m_sb.sb_rextsize += tp->t_rextsize_delta; mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta; From patchwork Wed Apr 14 19:52:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gao Xiang X-Patchwork-Id: 12203679 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=-18.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, 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 03ACEC433B4 for ; Wed, 14 Apr 2021 19:53:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DAA3B611AD for ; Wed, 14 Apr 2021 19:53:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353535AbhDNTyH (ORCPT ); Wed, 14 Apr 2021 15:54:07 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:59528 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353550AbhDNTx7 (ORCPT ); Wed, 14 Apr 2021 15:53:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618430013; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H2vcVLA2HPh4J9YEjfsL5yuAM3SA9vDw2eq0hPaFB1g=; b=DA4PWmEHUUWgDJwI/d/VQ5SrDo0hLfHOdqWLIebQQRKTQ2FmMCusq+WRhjfHNsoQ3eEPIG 8IxGtZrrqZOoopEn671TZZOFRURTQjvOYeovduz1UlL1eRA41q9H64d+m32v2IhUEtwmCT hRFZy8CYq9XaqTzvYOHKYrY45HpX56I= Received: from mail-pj1-f70.google.com (mail-pj1-f70.google.com [209.85.216.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-437-IIZGyE-1POqEzrfSgPkjFA-1; Wed, 14 Apr 2021 15:53:32 -0400 X-MC-Unique: IIZGyE-1POqEzrfSgPkjFA-1 Received: by mail-pj1-f70.google.com with SMTP id k12-20020a17090a590cb029014dd8eb8647so10951842pji.7 for ; Wed, 14 Apr 2021 12:53:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=H2vcVLA2HPh4J9YEjfsL5yuAM3SA9vDw2eq0hPaFB1g=; b=a/LkqK/bVtLe794rtLsoRl5fttBJ8X58xnLyJekfOKTnjxmH5UxlnmSf1wBrtFNMcb b6FmQsJStptY4mTPC5kXyse0ecOc4kakx2c0K9segU2rSKtHpP//hKaGFpL9EyJnMcdd eWa3KiMbtgyY4JhXn3+tIX1ZgHaiPaarZ6s3XLNayTsW2yoXmp2Eh7f0zvdVZQ9Q/rGN hEL8y1ssp9Ua28QK1/+7L6YfaBsV9NfGAvfA5gk18a6ydJ5WDm8LD6FScDH/r8mi2VYa SWrvZAYmUkIVa9nuh1eqO1hLGxMPiJRkPV8RR4pmklyuItd7302HKQzviLhUJfc4rg0G hD+Q== X-Gm-Message-State: AOAM530N/CP/Jkcvk/JBho9FzUZwBUnOvLR1BEVd+EGhVbmLYUT0l/2J szJjuHAkBRXZtpxockKt+HfZxeOge9AGuErW5SsAK651hui6wtLyLTA5+FY+RsB1zrVK/+boin/ iFWj7t/t566RvdgftnSTLKu04JqI1hAiYmYU+x+w2HNi314U2WHXFGQJw2u6OcRAAX+mo+zh8pg == X-Received: by 2002:a62:5fc6:0:b029:24d:e86b:dd38 with SMTP id t189-20020a625fc60000b029024de86bdd38mr14638139pfb.64.1618430010545; Wed, 14 Apr 2021 12:53:30 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwVzGRfZI0Z+LWYUMtl1z95U1xQMCWIfgXtO5K7YXY0ltRktz7D8cTAdbICGriuChDXtpkB1Q== X-Received: by 2002:a62:5fc6:0:b029:24d:e86b:dd38 with SMTP id t189-20020a625fc60000b029024de86bdd38mr14638119pfb.64.1618430010192; Wed, 14 Apr 2021 12:53:30 -0700 (PDT) Received: from xiangao.remote.csb ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id 11sm215787pjm.0.2021.04.14.12.53.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Apr 2021 12:53:29 -0700 (PDT) From: Gao Xiang To: linux-xfs@vger.kernel.org Cc: Gao Xiang Subject: [RFC PATCH 4/4] xfs: support shrinking empty AGs Date: Thu, 15 Apr 2021 03:52:40 +0800 Message-Id: <20210414195240.1802221-5-hsiangkao@redhat.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210414195240.1802221-1-hsiangkao@redhat.com> References: <20210414195240.1802221-1-hsiangkao@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org Roughly, freespace can be shrinked atomicly with the following steps: - make sure the pending-for-discard AGs are all stablized as empty; - a transaction to fix up freespace btrees for the target tail AG; decrease agcount to the target value. In order to make sure such AGs are empty, first to mark them as inactive, then check if these AGs are all empty one-by-one. Also need to log force, complete all discard operations together. Even it's needed to drain out all related cached buffers in case of corrupt fs if growfs again, so ail items are all needed to be pushed out as well. Signed-off-by: Gao Xiang --- fs/xfs/libxfs/xfs_ag.c | 1 - fs/xfs/libxfs/xfs_ag.h | 2 +- fs/xfs/xfs_fsops.c | 148 ++++++++++++++++++++++++++++++++++++++--- fs/xfs/xfs_mount.c | 87 +++++++++++++++++++----- fs/xfs/xfs_trans.c | 1 - 5 files changed, 210 insertions(+), 29 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c index ba5702e5c9ad..eb370fbae192 100644 --- a/fs/xfs/libxfs/xfs_ag.c +++ b/fs/xfs/libxfs/xfs_ag.c @@ -512,7 +512,6 @@ xfs_ag_shrink_space( struct xfs_agf *agf; int error, err2; - ASSERT(agno == mp->m_sb.sb_agcount - 1); error = xfs_ialloc_read_agi(mp, *tpp, agno, &agibp); if (error) return error; diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h index 4535de1d88ea..7031e2c7ef66 100644 --- a/fs/xfs/libxfs/xfs_ag.h +++ b/fs/xfs/libxfs/xfs_ag.h @@ -15,7 +15,7 @@ struct aghdr_init_data { xfs_agblock_t agno; /* ag to init */ xfs_extlen_t agsize; /* new AG size */ struct list_head buffer_list; /* buffer writeback list */ - xfs_rfsblock_t nfree; /* cumulative new free space */ + int64_t nfree; /* cumulative new free space */ /* per header data */ xfs_daddr_t daddr; /* header location */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b33c894b6cf3..659ca1836bba 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -14,11 +14,14 @@ #include "xfs_trans.h" #include "xfs_error.h" #include "xfs_alloc.h" +#include "xfs_ialloc.h" +#include "xfs_extent_busy.h" #include "xfs_fsops.h" #include "xfs_trans_space.h" #include "xfs_log.h" #include "xfs_ag.h" #include "xfs_ag_resv.h" +#include "xfs_trans_priv.h" /* * Write new AG headers to disk. Non-transactional, but need to be @@ -78,6 +81,112 @@ xfs_resizefs_init_new_ags( return error; } +static int +xfs_shrinkfs_deactivate_ags( + struct xfs_mount *mp, + xfs_agnumber_t oagcount, + xfs_agnumber_t nagcount) +{ + xfs_agnumber_t agno; + int error; + + /* confirm AGs pending for shrinking are all inactive */ + for (agno = nagcount; agno < oagcount; ++agno) { + struct xfs_buf *agfbp, *agibp; + struct xfs_perag *pag = xfs_perag_get(mp, agno); + + down_write(&pag->pag_inactive_rwsem); + /* need to lock agi, agf buffers here to close all races */ + error = xfs_read_agi(mp, NULL, agno, &agibp); + if (!error) { + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agfbp); + if (!error) { + pag->pag_inactive = true; + xfs_buf_relse(agfbp); + } + xfs_buf_relse(agibp); + } + up_write(&pag->pag_inactive_rwsem); + xfs_perag_put(pag); + if (error) + break; + } + return error; +} + +static void +xfs_shrinkfs_activate_ags( + struct xfs_mount *mp, + xfs_agnumber_t oagcount, + xfs_agnumber_t nagcount) +{ + xfs_agnumber_t agno; + + for (agno = nagcount; agno < oagcount; ++agno) { + struct xfs_perag *pag = xfs_perag_get(mp, agno); + + down_write(&pag->pag_inactive_rwsem); + pag->pag_inactive = false; + up_write(&pag->pag_inactive_rwsem); + } +} + +static int +xfs_shrinkfs_prepare_ags( + struct xfs_mount *mp, + struct aghdr_init_data *id, + xfs_agnumber_t oagcount, + xfs_agnumber_t nagcount) +{ + xfs_agnumber_t agno; + int error; + + error = xfs_shrinkfs_deactivate_ags(mp, oagcount, nagcount); + if (error) + goto err_out; + + /* confirm AGs pending for shrinking are all empty */ + for (agno = nagcount; agno < oagcount; ++agno) { + struct xfs_buf *agfbp; + struct xfs_perag *pag; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agfbp); + if (error) + goto err_out; + + pag = agfbp->b_pag; + error = xfs_ag_resv_free(pag); + if (!error) { + error = xfs_ag_is_empty(agfbp); + if (!error) { + ASSERT(!pag->pagf_flcount); + id->nfree -= pag->pagf_freeblks; + } + } + xfs_buf_relse(agfbp); + if (error) + goto err_out; + } + xfs_log_force(mp, XFS_LOG_SYNC); + /* + * Wait for all busy extents to be freed, including completion of + * any discard operation. + */ + xfs_extent_busy_wait_all(mp); + flush_workqueue(xfs_discard_wq); + + /* + * Also need to drain out all related cached buffers, at least, + * in case of growfs back later (which uses uncached buffers.) + */ + xfs_ail_push_all_sync(mp->m_ail); + xfs_buftarg_drain(mp->m_ddev_targp); + return error; +err_out: + xfs_shrinkfs_activate_ags(mp, oagcount, nagcount); + return error; +} + /* * growfs operations */ @@ -93,7 +202,7 @@ xfs_growfs_data_private( xfs_rfsblock_t nb, nb_div, nb_mod; int64_t delta; bool lastag_extended; - xfs_agnumber_t oagcount; + xfs_agnumber_t oagcount, agno; struct xfs_trans *tp; struct aghdr_init_data id = {}; @@ -130,14 +239,13 @@ xfs_growfs_data_private( oagcount = mp->m_sb.sb_agcount; /* allocate the new per-ag structures */ - if (nagcount > oagcount) { + if (nagcount > oagcount) error = xfs_initialize_perag(mp, nagcount, &nagimax); - if (error) - return error; - } else if (nagcount < oagcount) { - /* TODO: shrinking the entire AGs hasn't yet completed */ - return -EINVAL; - } + else if (nagcount < oagcount) + error = xfs_shrinkfs_prepare_ags(mp, &id, oagcount, nagcount); + + if (error) + return error; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata, (delta > 0 ? XFS_GROWFS_SPACE_RES(mp) : -delta), 0, @@ -151,13 +259,29 @@ xfs_growfs_data_private( } else { static struct ratelimit_state shrink_warning = \ RATELIMIT_STATE_INIT("shrink_warning", 86400 * HZ, 1); + xfs_agblock_t agdelta; + ratelimit_set_flags(&shrink_warning, RATELIMIT_MSG_ON_RELEASE); if (__ratelimit(&shrink_warning)) xfs_alert(mp, "EXPERIMENTAL online shrink feature in use. Use at your own risk!"); - error = xfs_ag_shrink_space(mp, &tp, nagcount - 1, -delta); + for (agno = nagcount; agno < oagcount; ++agno) { + struct xfs_perag *pag = xfs_perag_get(mp, agno); + + pag->pagf_freeblks = 0; + pag->pagf_longest = 0; + xfs_perag_put(pag); + } + + xfs_trans_agblocks_delta(tp, id.nfree); + + if (nagcount != oagcount) + agdelta = nagcount * mp->m_sb.sb_agblocks - nb; + else + agdelta = -delta; + error = xfs_ag_shrink_space(mp, &tp, nagcount - 1, agdelta); } if (error) goto out_trans_cancel; @@ -167,8 +291,10 @@ xfs_growfs_data_private( * seen by the rest of the world until the transaction commit applies * them atomically to the superblock. */ - if (nagcount > oagcount) - xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount); + if (nagcount != oagcount) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, + (int64_t)nagcount - (int64_t)oagcount); + if (delta) xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS, delta); if (id.nfree) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 69a60b5f4a32..ca9513fdc09e 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -172,6 +172,47 @@ xfs_sb_validate_fsb_count( return 0; } +static int +xfs_perag_reset( + struct xfs_perag *pag) +{ + int error; + + spin_lock_init(&pag->pag_ici_lock); + INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker); + INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); + + error = xfs_buf_hash_init(pag); + if (error) + return error; + + init_waitqueue_head(&pag->pagb_wait); + spin_lock_init(&pag->pagb_lock); + pag->pagb_count = 0; + pag->pagb_tree = RB_ROOT; + + error = xfs_iunlink_init(pag); + if (error) { + xfs_buf_hash_destroy(pag); + return error; + } + spin_lock_init(&pag->pag_state_lock); + return 0; +} + +static int +xfs_perag_inactive_reset( + struct xfs_perag *pag) +{ + cancel_delayed_work_sync(&pag->pag_blockgc_work); + xfs_iunlink_destroy(pag); + xfs_buf_hash_destroy(pag); + + memset((char *)pag + offsetof(struct xfs_perag, pag_inactive), 0, + sizeof(*pag) - offsetof(struct xfs_perag, pag_inactive)); + return xfs_perag_reset(pag); +} + int xfs_initialize_perag( xfs_mount_t *mp, @@ -180,6 +221,8 @@ xfs_initialize_perag( { xfs_agnumber_t index; xfs_agnumber_t first_initialised = NULLAGNUMBER; + xfs_agnumber_t first_inactive = NULLAGNUMBER; + xfs_agnumber_t last_inactive = NULLAGNUMBER; xfs_perag_t *pag; int error = -ENOMEM; @@ -191,6 +234,20 @@ xfs_initialize_perag( for (index = 0; index < agcount; index++) { pag = xfs_perag_get(mp, index); if (pag) { + down_write(&pag->pag_inactive_rwsem); + if (pag->pag_inactive) { + error = xfs_perag_inactive_reset(pag); + if (error) { + pag->pag_inactive = true; + up_write(&pag->pag_inactive_rwsem); + xfs_perag_put(pag); + goto out_unwind_new_pags; + } + if (first_inactive == NULLAGNUMBER) + first_inactive = index; + last_inactive = index; + } + up_write(&pag->pag_inactive_rwsem); xfs_perag_put(pag); continue; } @@ -200,19 +257,13 @@ xfs_initialize_perag( error = -ENOMEM; goto out_unwind_new_pags; } + pag->pag_agno = index; pag->pag_mount = mp; - spin_lock_init(&pag->pag_ici_lock); - INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker); - INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); - - error = xfs_buf_hash_init(pag); + init_rwsem(&pag->pag_inactive_rwsem); + error = xfs_perag_reset(pag); if (error) goto out_free_pag; - init_waitqueue_head(&pag->pagb_wait); - spin_lock_init(&pag->pagb_lock); - pag->pagb_count = 0; - pag->pagb_tree = RB_ROOT; error = radix_tree_preload(GFP_NOFS); if (error) @@ -231,12 +282,6 @@ xfs_initialize_perag( /* first new pag is fully initialized */ if (first_initialised == NULLAGNUMBER) first_initialised = index; - error = xfs_iunlink_init(pag); - if (error) - goto out_hash_destroy; - spin_lock_init(&pag->pag_state_lock); - - init_rwsem(&pag->pag_inactive_rwsem); } index = xfs_set_inode_alloc(mp, agcount); @@ -252,6 +297,18 @@ xfs_initialize_perag( out_free_pag: kmem_free(pag); out_unwind_new_pags: + if (first_inactive != NULLAGNUMBER) { + for (index = first_inactive; index <= last_inactive; ++index) { + pag = xfs_perag_get(mp, index); + if (pag) { + down_write(&pag->pag_inactive_rwsem); + pag->pag_inactive = true; + up_write(&pag->pag_inactive_rwsem); + xfs_perag_put(pag); + } + } + } + /* unwind any prior newly initialized pags */ for (index = first_initialised; index < agcount; index++) { pag = radix_tree_delete(&mp->m_perag_tree, index); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 1d37de86fc09..7fc7e0d1fde6 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -439,7 +439,6 @@ xfs_trans_mod_sb( tp->t_dblocks_delta += delta; break; case XFS_TRANS_SB_AGCOUNT: - ASSERT(delta > 0); tp->t_agcount_delta += delta; break; case XFS_TRANS_SB_IMAXPCT: