From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1D4DD7CAF for ; Wed, 13 Apr 2016 00:32:25 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id E0F9830405F for ; Tue, 12 Apr 2016 22:32:24 -0700 (PDT) Received: from ipmail04.adl6.internode.on.net (ipmail04.adl6.internode.on.net [150.101.137.141]) by cuda.sgi.com with ESMTP id GIwkKfsy25KDpC2w for ; Tue, 12 Apr 2016 22:32:16 -0700 (PDT) Received: from disappointment.disaster.area ([192.168.1.110] helo=disappointment) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1aqDPP-0003p5-ST for xfs@oss.sgi.com; Wed, 13 Apr 2016 15:32:11 +1000 Received: from dave by disappointment with local (Exim 4.86) (envelope-from ) id 1aqDOq-0000bx-Cm for xfs@oss.sgi.com; Wed, 13 Apr 2016 15:31:36 +1000 From: Dave Chinner Subject: [PATCH 05/11] xfs: optimise xfs_iext_destroy Date: Wed, 13 Apr 2016 15:31:26 +1000 Message-Id: <1460525492-1170-6-git-send-email-david@fromorbit.com> In-Reply-To: <1460525492-1170-1-git-send-email-david@fromorbit.com> References: <1460525492-1170-1-git-send-email-david@fromorbit.com> List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com To: xfs@oss.sgi.com From: Alex Lyakas When unmounting XFS, we call: xfs_inode_free => xfs_idestroy_fork => xfs_iext_destroy This goes over the whole indirection array and calls xfs_iext_irec_remove for each one of the erps (from the last one to the first one). As a result, we keep shrinking (reallocating actually) the indirection array until we shrink out all of its elements. When we have files with huge numbers of extents, umount takes 30-80 sec, depending on the amount of files that XFS loaded and the amount of indirection entries of each file. The unmount stack looks like: [] xfs_iext_realloc_indirect+0x40/0x60 [xfs] [] xfs_iext_irec_remove+0xee/0xf0 [xfs] [] xfs_iext_destroy+0x3d/0xb0 [xfs] [] xfs_idestroy_fork+0xb6/0xf0 [xfs] [] xfs_inode_free+0xb2/0xc0 [xfs] [] xfs_reclaim_inode+0x250/0x340 [xfs] [] xfs_reclaim_inodes_ag+0x233/0x370 [xfs] [] xfs_reclaim_inodes+0x1d/0x20 [xfs] [] xfs_unmountfs+0x7b/0x1a0 [xfs] [] xfs_fs_put_super+0x2d/0x70 [xfs] [] generic_shutdown_super+0x76/0x100 [] kill_block_super+0x27/0x70 [] deactivate_locked_super+0x49/0x60 [] deactivate_super+0x4e/0x70 [] cleanup_mnt+0x43/0x90 [] __cleanup_mnt+0x12/0x20 [] task_work_run+0xa7/0xe0 [] do_notify_resume+0x97/0xb0 [] int_signal+0x12/0x17 Further, this reallocation prevents us from freeing the extent list from a RCU callback as allocation can block. Hence if the extent list is in indirect format, optimise the freeing of the extent list to only use kmem_free calls by freeing entire extent buffer pages at a time, rather than extent by extent. Signed-off-by: Alex Lyakas Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_inode_fork.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index d3d1477..27497e1 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -1519,6 +1519,26 @@ xfs_iext_indirect_to_direct( } /* + * Remove all records from the indirection array. + */ +STATIC void +xfs_iext_irec_remove_all( + struct xfs_ifork *ifp) +{ + int nlists; + int i; + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + for (i = 0; i < nlists; i++) { + xfs_ext_irec_t *erp = &ifp->if_u1.if_ext_irec[i]; + if (erp->er_extbuf) + kmem_free(erp->er_extbuf); + } + kmem_free(ifp->if_u1.if_ext_irec); +} + +/* * Free incore file extents. */ void @@ -1526,13 +1546,7 @@ xfs_iext_destroy( xfs_ifork_t *ifp) /* inode fork pointer */ { if (ifp->if_flags & XFS_IFEXTIREC) { - int erp_idx; - int nlists; - - nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; - for (erp_idx = nlists - 1; erp_idx >= 0 ; erp_idx--) { - xfs_iext_irec_remove(ifp, erp_idx); - } + xfs_iext_irec_remove_all(ifp); ifp->if_flags &= ~XFS_IFEXTIREC; } else if (ifp->if_real_bytes) { kmem_free(ifp->if_u1.if_extents); -- 2.7.0 _______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs